cert-object.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. /* cert-object.c - Convert a GPGSM certificate into a PKCS #11 object.
  2. Copyright (C) 2006, 2007 g10 Code GmbH
  3. This file is part of Scute.
  4. Scute is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. Scute is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with Scute; if not, write to the Free Software Foundation,
  14. Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. In addition, as a special exception, g10 Code GmbH gives permission
  16. to link this library: with the Mozilla Foundation's code for
  17. Mozilla (or with modified versions of it that use the same license
  18. as the "Mozilla" code), and distribute the linked executables. You
  19. must obey the GNU General Public License in all respects for all of
  20. the code used other than "Mozilla". If you modify this file, you
  21. may extend this exception to your version of the file, but you are
  22. not obligated to do so. If you do not wish to do so, delete this
  23. exception statement from your version. */
  24. #if HAVE_CONFIG_H
  25. #include <config.h>
  26. #endif
  27. #include <stdbool.h>
  28. #include <stdlib.h>
  29. #include <assert.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <gpg-error.h>
  33. #include "cryptoki.h"
  34. #include "support.h"
  35. #include "cert.h"
  36. #define atoi_1(p) (*(p) - '0' )
  37. #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1))
  38. #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2))
  39. static bool
  40. time_to_ck_date (time_t *atime, CK_DATE *ckdate)
  41. {
  42. struct tm broken_time;
  43. int nr;
  44. if (!*atime)
  45. return false;
  46. #ifdef HAVE_LOCALTIME_R
  47. if (!localtime_r (atime, &broken_time))
  48. return false;
  49. #else
  50. {
  51. /* FIXME: This is not thread-safe, but it minimizes risk. */
  52. struct tm *b_time = localtime (atime);
  53. if (!b_time)
  54. return false;
  55. memcpy (&broken_time, b_time, sizeof (*b_time));
  56. }
  57. #endif
  58. /* We can only represent years until 9999. */
  59. if (!(broken_time.tm_year >= 0 && broken_time.tm_year <= 8099
  60. && broken_time.tm_mon >= 0 && broken_time.tm_mon <= 11
  61. && broken_time.tm_mday >= 1 && broken_time.tm_mday <= 31))
  62. return false;
  63. #define LAST_DIGIT(d) (((d) % 10) + '0')
  64. nr = broken_time.tm_year + 1900;
  65. ckdate->year[3] = LAST_DIGIT (nr);
  66. nr = nr / 10;
  67. ckdate->year[2] = LAST_DIGIT (nr);
  68. nr = nr / 10;
  69. ckdate->year[1] = LAST_DIGIT (nr);
  70. nr = nr / 10;
  71. ckdate->year[0] = LAST_DIGIT (nr);
  72. nr = broken_time.tm_mon + 1;
  73. ckdate->month[1] = LAST_DIGIT (nr);
  74. nr = nr / 10;
  75. ckdate->month[0] = LAST_DIGIT (nr);
  76. nr = broken_time.tm_mday;
  77. ckdate->day[1] = LAST_DIGIT (nr);
  78. nr = nr / 10;
  79. ckdate->day[0] = LAST_DIGIT (nr);
  80. return true;
  81. }
  82. static gpg_error_t
  83. asn1_get_len (unsigned char **asn1, int *asn1_len, int *rlen)
  84. {
  85. unsigned char *ptr = *asn1;
  86. int len = *asn1_len;
  87. int cnt;
  88. int result = 0;
  89. if (len < 1)
  90. return gpg_error (GPG_ERR_GENERAL);
  91. if (*ptr & 0x80)
  92. {
  93. cnt = *ptr & 0x7f;
  94. ptr++;
  95. len--;
  96. }
  97. else
  98. cnt = 1;
  99. /* We only support a limited number of length bytes. */
  100. if (cnt > 2 || len < cnt)
  101. return gpg_error (GPG_ERR_GENERAL);
  102. while (cnt--)
  103. {
  104. result = (result << 8) | *ptr;
  105. ptr++;
  106. len--;
  107. }
  108. *asn1 = ptr;
  109. *asn1_len = len;
  110. *rlen = result;
  111. return 0;
  112. }
  113. /* A path to an ASN.1 element that can be looked up with
  114. asn1_get_element. The last element in the list is returned (that
  115. one should have ENTER being false. */
  116. struct asn1_path
  117. {
  118. unsigned char tag;
  119. /* True if we should enter the element, false if we should skip
  120. it. */
  121. bool enter;
  122. };
  123. static gpg_error_t
  124. asn1_get_element (unsigned char *cert, int cert_len,
  125. unsigned char **sub_start, int *sub_len,
  126. struct asn1_path *path, int path_size)
  127. {
  128. gpg_error_t err;
  129. unsigned char *prev_certp = NULL;
  130. unsigned char *certp = cert;
  131. int cert_left = cert_len;
  132. int len;
  133. int i;
  134. for (i = 0; i < path_size; i++)
  135. {
  136. prev_certp = certp;
  137. if (cert_left < 1 || *certp != path[i].tag)
  138. return gpg_error (GPG_ERR_GENERAL);
  139. certp++;
  140. cert_left--;
  141. err = asn1_get_len (&certp, &cert_left, &len);
  142. if (err)
  143. return err;
  144. if (!path[i].enter)
  145. {
  146. if (cert_left < len)
  147. return gpg_error (GPG_ERR_GENERAL);
  148. certp += len;
  149. cert_left -= len;
  150. }
  151. else
  152. {
  153. /* Special code to deal with ASN.1 data encapsulated in a
  154. bit string. */
  155. if (path[i].tag == '\x03')
  156. {
  157. if (cert_left < 1 || *certp != '\x00')
  158. return gpg_error (GPG_ERR_GENERAL);
  159. certp++;
  160. cert_left--;
  161. }
  162. }
  163. }
  164. /* We found the subject. */
  165. *sub_start = prev_certp;
  166. *sub_len = certp - prev_certp;
  167. return 0;
  168. }
  169. static gpg_error_t
  170. asn1_get_issuer (unsigned char *cert, int cert_len,
  171. unsigned char **sub_start, int *sub_len)
  172. {
  173. /* The path to the issuer entry in the DER file. This is
  174. Sequence->Sequence->Version,Serial,AlgID,Issuer. */
  175. struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
  176. { '\xa0', false }, { '\x02', false },
  177. { '\x30', false }, { '\x30', false } };
  178. return asn1_get_element (cert, cert_len, sub_start, sub_len,
  179. path, DIM (path));
  180. }
  181. static gpg_error_t
  182. asn1_get_subject (unsigned char *cert, int cert_len,
  183. unsigned char **sub_start, int *sub_len)
  184. {
  185. /* The path to the subject entry in the DER file. This is
  186. Sequence->Sequence->Version,Serial,AlgID,Issuer,Time,Subject. */
  187. struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
  188. { '\xa0', false }, { '\x02', false },
  189. { '\x30', false }, { '\x30', false },
  190. { '\x30', false }, { '\x30', false } };
  191. return asn1_get_element (cert, cert_len, sub_start, sub_len,
  192. path, DIM (path));
  193. }
  194. static gpg_error_t
  195. asn1_get_serial (unsigned char *cert, int cert_len,
  196. unsigned char **sub_start, int *sub_len)
  197. {
  198. /* The path to the serial entry in the DER file. This is
  199. Sequence->Sequence->Version,Serial. */
  200. struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
  201. { '\xa0', false }, { '\x02', false } };
  202. return asn1_get_element (cert, cert_len, sub_start, sub_len,
  203. path, DIM (path));
  204. }
  205. static gpg_error_t
  206. asn1_get_modulus (unsigned char *cert, int cert_len,
  207. unsigned char **sub_start, int *sub_len)
  208. {
  209. gpg_error_t err;
  210. int len;
  211. struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
  212. { '\xa0', false }, { '\x02', false },
  213. { '\x30', false }, { '\x30', false },
  214. { '\x30', false }, { '\x30', false },
  215. { '\x30', true }, { '\x30', false },
  216. { '\x03', true }, { '\x30', true },
  217. { '\x02', false } };
  218. /* The path to the modulus entry in the DER file. This is
  219. Sequence->Sequence->Version,Serial,AlgID,Issuer,Time,Subject,
  220. Sequence->Sequence,Bitstring->Sequence->Integer,Integer */
  221. err = asn1_get_element (cert, cert_len, sub_start, sub_len,
  222. path, DIM (path));
  223. if (err)
  224. return err;
  225. if (*sub_len < 1)
  226. return gpg_error (GPG_ERR_GENERAL);
  227. (*sub_start)++;
  228. (*sub_len)--;
  229. err = asn1_get_len (sub_start, sub_len, &len);
  230. if (err)
  231. return err;
  232. /* PKCS #11 expects an unsigned big integer. */
  233. while (**sub_start == '\x00' && *sub_len > 0)
  234. {
  235. (*sub_start)++;
  236. (*sub_len)--;
  237. }
  238. return 0;
  239. }
  240. static gpg_error_t
  241. asn1_get_public_exp (unsigned char *cert, int cert_len,
  242. unsigned char **sub_start, int *sub_len)
  243. {
  244. gpg_error_t err;
  245. int len;
  246. /* The path to the public exp entry in the DER file. This is
  247. Sequence->Sequence->Version,Serial,AlgID,Issuer,Time,Subject,
  248. Sequence->Sequence,Bitstring->Sequence->Integer,Integer */
  249. struct asn1_path path[] = { { '\x30', true }, { '\x30', true },
  250. { '\xa0', false }, { '\x02', false },
  251. { '\x30', false }, { '\x30', false },
  252. { '\x30', false }, { '\x30', false },
  253. { '\x30', true }, { '\x30', false },
  254. { '\x03', true }, { '\x30', true },
  255. { '\x02', false }, { '\x02', false } };
  256. err = asn1_get_element (cert, cert_len, sub_start, sub_len,
  257. path, DIM (path));
  258. if (err)
  259. return err;
  260. if (*sub_len < 1)
  261. return gpg_error (GPG_ERR_GENERAL);
  262. (*sub_start)++;
  263. (*sub_len)--;
  264. err = asn1_get_len (sub_start, sub_len, &len);
  265. if (err)
  266. return err;
  267. /* PKCS #11 expects an unsigned big integer. */
  268. while (**sub_start == '\x00' && *sub_len > 0)
  269. {
  270. (*sub_start)++;
  271. (*sub_len)--;
  272. }
  273. return 0;
  274. }
  275. static gpg_error_t
  276. attr_one (CK_ATTRIBUTE_PTR attr, CK_ULONG *attr_count,
  277. CK_ATTRIBUTE_TYPE type, CK_VOID_PTR val, CK_ULONG size)
  278. {
  279. CK_ULONG i = *attr_count;
  280. attr[i].type = type;
  281. attr[i].ulValueLen = size;
  282. attr[i].pValue = malloc (size);
  283. if (attr[i].pValue == NULL)
  284. return gpg_error (GPG_ERR_ENOMEM);
  285. memcpy (attr[i].pValue, val, size);
  286. (*attr_count)++;
  287. return 0;
  288. }
  289. static gpg_error_t
  290. attr_empty (CK_ATTRIBUTE_PTR attr, CK_ULONG *attr_count,
  291. CK_ATTRIBUTE_TYPE type)
  292. {
  293. CK_ULONG i = *attr_count;
  294. attr[i].type = type;
  295. attr[i].ulValueLen = 0;
  296. attr[i].pValue = NULL_PTR;
  297. (*attr_count)++;
  298. return 0;
  299. }
  300. void
  301. scute_attr_free (CK_ATTRIBUTE_PTR attr, CK_ULONG attr_count)
  302. {
  303. while (0 < attr_count--)
  304. free (attr[attr_count].pValue);
  305. }
  306. gpg_error_t
  307. scute_attr_cert (struct cert *cert,
  308. CK_ATTRIBUTE_PTR *attrp, CK_ULONG *attr_countp)
  309. {
  310. CK_RV err;
  311. CK_ATTRIBUTE_PTR attr;
  312. CK_ULONG attr_count;
  313. unsigned char *subject_start;
  314. int subject_len;
  315. unsigned char *issuer_start;
  316. int issuer_len;
  317. unsigned char *serial_start;
  318. int serial_len;
  319. CK_OBJECT_CLASS obj_class = CKO_CERTIFICATE;
  320. CK_BBOOL obj_token = CK_TRUE;
  321. CK_BBOOL obj_private = CK_FALSE;
  322. CK_BBOOL obj_modifiable = CK_FALSE;
  323. CK_BYTE obj_label[] = { 'D', 'u', 'm', 'm', 'y', ' ',
  324. 'L', 'a', 'b', 'e', 'l' };
  325. CK_CERTIFICATE_TYPE obj_cert_type = CKC_X_509;
  326. CK_BBOOL obj_trusted = cert->is_trusted;
  327. CK_ULONG obj_cert_cat = 0;
  328. CK_BYTE obj_check_value[3] = { '\0', '\0', '\0' };
  329. CK_DATE obj_start_date;
  330. CK_DATE obj_end_date;
  331. CK_ULONG obj_java_midp_sec_domain = 0;
  332. err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
  333. &subject_start, &subject_len);
  334. if (!err)
  335. err = asn1_get_issuer (cert->cert_der, cert->cert_der_len,
  336. &issuer_start, &issuer_len);
  337. if (!err)
  338. err = asn1_get_serial (cert->cert_der, cert->cert_der_len,
  339. &serial_start, &serial_len);
  340. if (err)
  341. return err;
  342. #define NR_ATTR_CERT 20
  343. attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_CERT);
  344. attr_count = 0;
  345. if (!attr)
  346. return gpg_error (GPG_ERR_ENOMEM);
  347. #define one_attr_ext(type, val, size) \
  348. if (!err) \
  349. err = attr_one (attr, &attr_count, type, val, size)
  350. #define one_attr(type, val) one_attr_ext (type, &val, sizeof (val))
  351. #define empty_attr(type) \
  352. if (!err) \
  353. err = attr_empty (attr, &attr_count, type)
  354. one_attr (CKA_CLASS, obj_class);
  355. one_attr (CKA_TOKEN, obj_token);
  356. one_attr (CKA_PRIVATE, obj_private);
  357. one_attr (CKA_MODIFIABLE, obj_modifiable);
  358. one_attr (CKA_LABEL, obj_label);
  359. one_attr (CKA_CERTIFICATE_TYPE, obj_cert_type);
  360. one_attr (CKA_TRUSTED, obj_trusted);
  361. one_attr (CKA_CERTIFICATE_CATEGORY, obj_cert_cat);
  362. /* FIXME: Calculate check_value. */
  363. one_attr (CKA_CHECK_VALUE, obj_check_value);
  364. if (time_to_ck_date (&cert->timestamp, &obj_start_date))
  365. {
  366. one_attr (CKA_START_DATE, obj_start_date);
  367. }
  368. else
  369. {
  370. empty_attr (CKA_START_DATE);
  371. }
  372. if (time_to_ck_date (&cert->expires, &obj_end_date))
  373. {
  374. one_attr (CKA_END_DATE, obj_end_date);
  375. }
  376. else
  377. {
  378. empty_attr (CKA_END_DATE);
  379. }
  380. one_attr_ext (CKA_SUBJECT, subject_start, subject_len);
  381. one_attr_ext (CKA_ID, cert->fpr, 40);
  382. one_attr_ext (CKA_ISSUER, issuer_start, issuer_len);
  383. one_attr_ext (CKA_SERIAL_NUMBER, serial_start, serial_len);
  384. one_attr_ext (CKA_VALUE, cert->cert_der, cert->cert_der_len);
  385. empty_attr (CKA_URL);
  386. empty_attr (CKA_HASH_OF_SUBJECT_PUBLIC_KEY);
  387. empty_attr (CKA_HASH_OF_ISSUER_PUBLIC_KEY);
  388. one_attr (CKA_JAVA_MIDP_SECURITY_DOMAIN, obj_java_midp_sec_domain);
  389. if (err)
  390. {
  391. scute_attr_free (attr, attr_count);
  392. return err;
  393. }
  394. /* FIXME: Not completely safe. */
  395. assert (NR_ATTR_CERT == attr_count);
  396. *attrp = attr;
  397. *attr_countp = attr_count;
  398. return 0;
  399. }
  400. gpg_error_t
  401. scute_attr_prv (struct cert *cert, CK_ATTRIBUTE_PTR *attrp,
  402. CK_ULONG *attr_countp)
  403. {
  404. CK_RV err;
  405. CK_ATTRIBUTE_PTR attr;
  406. CK_ULONG attr_count;
  407. unsigned char *subject_start;
  408. int subject_len;
  409. unsigned char *modulus_start;
  410. int modulus_len;
  411. unsigned char *public_exp_start;
  412. int public_exp_len;
  413. CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY;
  414. CK_BBOOL obj_token = CK_TRUE;
  415. CK_BBOOL obj_private = CK_FALSE;
  416. CK_BBOOL obj_modifiable = CK_FALSE;
  417. CK_BYTE obj_label[] = { 'O', 'P', 'E', 'N', 'P', 'G',
  418. 'P', '.', '3' };
  419. CK_KEY_TYPE obj_key_type = CKK_RSA;
  420. CK_DATE obj_start_date;
  421. CK_DATE obj_end_date;
  422. CK_BBOOL obj_derive = CK_FALSE;
  423. CK_BBOOL obj_local = CK_FALSE; /* FIXME: Unknown. */
  424. CK_MECHANISM_TYPE obj_key_gen = CKM_RSA_PKCS_KEY_PAIR_GEN;
  425. CK_MECHANISM_TYPE obj_mechanisms[] = { CKM_RSA_PKCS };
  426. CK_BBOOL obj_sensitive = CK_TRUE;
  427. CK_BBOOL obj_decrypt = CK_FALSE; /* Authentication only for now. */
  428. CK_BBOOL obj_sign = CK_TRUE;
  429. CK_BBOOL obj_sign_recover = CK_FALSE;
  430. CK_BBOOL obj_unwrap = CK_FALSE;
  431. CK_BBOOL obj_extractable = CK_FALSE;
  432. CK_BBOOL obj_always_sensitive = CK_TRUE;
  433. CK_BBOOL obj_never_extractable = CK_TRUE;
  434. CK_BBOOL obj_wrap_with_trusted = CK_FALSE;
  435. CK_BBOOL obj_always_authenticate = CK_FALSE;
  436. err = asn1_get_subject (cert->cert_der, cert->cert_der_len,
  437. &subject_start, &subject_len);
  438. if (!err)
  439. err = asn1_get_modulus (cert->cert_der, cert->cert_der_len,
  440. &modulus_start, &modulus_len);
  441. if (!err)
  442. err = asn1_get_public_exp (cert->cert_der, cert->cert_der_len,
  443. &public_exp_start, &public_exp_len);
  444. if (err)
  445. return err;
  446. #define NR_ATTR_PRV 27
  447. attr = malloc (sizeof (CK_ATTRIBUTE) * NR_ATTR_PRV);
  448. attr_count = 0;
  449. if (!attr)
  450. return gpg_error (GPG_ERR_ENOMEM);
  451. #undef one_attr_ext
  452. #define one_attr_ext(type, val, size) \
  453. if (!err) \
  454. err = attr_one (attr, &attr_count, type, val, size)
  455. #undef one_attr
  456. #define one_attr(type, val) one_attr_ext (type, &val, sizeof (val))
  457. #undef empty_attr
  458. #define empty_attr(type) \
  459. if (!err) \
  460. err = attr_empty (attr, &attr_count, type)
  461. one_attr (CKA_CLASS, obj_class);
  462. one_attr (CKA_TOKEN, obj_token);
  463. one_attr (CKA_PRIVATE, obj_private);
  464. one_attr (CKA_MODIFIABLE, obj_modifiable);
  465. one_attr (CKA_LABEL, obj_label);
  466. one_attr (CKA_KEY_TYPE, obj_key_type);
  467. one_attr_ext (CKA_ID, cert->fpr, 40);
  468. if (time_to_ck_date (&cert->timestamp, &obj_start_date))
  469. {
  470. one_attr (CKA_START_DATE, obj_start_date);
  471. }
  472. else
  473. {
  474. empty_attr (CKA_START_DATE);
  475. }
  476. if (time_to_ck_date (&cert->expires, &obj_end_date))
  477. {
  478. one_attr (CKA_END_DATE, obj_end_date);
  479. }
  480. else
  481. {
  482. empty_attr (CKA_END_DATE);
  483. }
  484. one_attr (CKA_DERIVE, obj_derive);
  485. one_attr (CKA_LOCAL, obj_local);
  486. one_attr (CKA_KEY_GEN_MECHANISM, obj_key_gen);
  487. one_attr (CKA_ALLOWED_MECHANISMS, obj_mechanisms);
  488. one_attr_ext (CKA_SUBJECT, subject_start, subject_len);
  489. one_attr (CKA_SENSITIVE, obj_sensitive);
  490. one_attr (CKA_DECRYPT, obj_decrypt);
  491. one_attr (CKA_SIGN, obj_sign);
  492. one_attr (CKA_SIGN_RECOVER, obj_sign_recover);
  493. one_attr (CKA_UNWRAP, obj_unwrap);
  494. one_attr (CKA_EXTRACTABLE, obj_extractable);
  495. one_attr (CKA_ALWAYS_SENSITIVE, obj_always_sensitive);
  496. one_attr (CKA_NEVER_EXTRACTABLE, obj_never_extractable);
  497. one_attr (CKA_WRAP_WITH_TRUSTED, obj_wrap_with_trusted);
  498. empty_attr (CKA_UNWRAP_TEMPLATE);
  499. one_attr (CKA_ALWAYS_AUTHENTICATE, obj_always_authenticate);
  500. one_attr_ext (CKA_MODULUS, modulus_start, modulus_len);
  501. one_attr_ext (CKA_PUBLIC_EXPONENT, public_exp_start, public_exp_len);
  502. if (err)
  503. {
  504. scute_attr_free (attr, attr_count);
  505. return err;
  506. }
  507. /* FIXME: Not completely safe. */
  508. assert (NR_ATTR_PRV == attr_count);
  509. *attrp = attr;
  510. *attr_countp = attr_count;
  511. return 0;
  512. }