pkcs8.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * PKCS #8 (Private-key information syntax)
  3. * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "asn1.h"
  17. #include "bignum.h"
  18. #include "rsa.h"
  19. #include "pkcs5.h"
  20. #include "pkcs8.h"
  21. struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len)
  22. {
  23. struct asn1_hdr hdr;
  24. const u8 *pos, *end;
  25. struct bignum *zero;
  26. struct asn1_oid oid;
  27. char obuf[80];
  28. /* PKCS #8, Chapter 6 */
  29. /* PrivateKeyInfo ::= SEQUENCE */
  30. if (asn1_get_next(buf, len, &hdr) < 0 ||
  31. hdr.class != ASN1_CLASS_UNIVERSAL ||
  32. hdr.tag != ASN1_TAG_SEQUENCE) {
  33. wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
  34. "header (SEQUENCE); assume PKCS #8 not used");
  35. return NULL;
  36. }
  37. pos = hdr.payload;
  38. end = pos + hdr.length;
  39. /* version Version (Version ::= INTEGER) */
  40. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  41. hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
  42. wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
  43. "class %d tag 0x%x; assume PKCS #8 not used",
  44. hdr.class, hdr.tag);
  45. return NULL;
  46. }
  47. zero = bignum_init();
  48. if (zero == NULL)
  49. return NULL;
  50. if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
  51. wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
  52. bignum_deinit(zero);
  53. return NULL;
  54. }
  55. pos = hdr.payload + hdr.length;
  56. if (bignum_cmp_d(zero, 0) != 0) {
  57. wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
  58. "beginning of private key; not found; assume "
  59. "PKCS #8 not used");
  60. bignum_deinit(zero);
  61. return NULL;
  62. }
  63. bignum_deinit(zero);
  64. /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
  65. * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
  66. if (asn1_get_next(pos, len, &hdr) < 0 ||
  67. hdr.class != ASN1_CLASS_UNIVERSAL ||
  68. hdr.tag != ASN1_TAG_SEQUENCE) {
  69. wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
  70. "(AlgorithmIdentifier) - found class %d tag 0x%x; "
  71. "assume PKCS #8 not used",
  72. hdr.class, hdr.tag);
  73. return NULL;
  74. }
  75. if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
  76. wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
  77. "(algorithm); assume PKCS #8 not used");
  78. return NULL;
  79. }
  80. asn1_oid_to_str(&oid, obuf, sizeof(obuf));
  81. wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
  82. if (oid.len != 7 ||
  83. oid.oid[0] != 1 /* iso */ ||
  84. oid.oid[1] != 2 /* member-body */ ||
  85. oid.oid[2] != 840 /* us */ ||
  86. oid.oid[3] != 113549 /* rsadsi */ ||
  87. oid.oid[4] != 1 /* pkcs */ ||
  88. oid.oid[5] != 1 /* pkcs-1 */ ||
  89. oid.oid[6] != 1 /* rsaEncryption */) {
  90. wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
  91. "algorithm %s", obuf);
  92. return NULL;
  93. }
  94. pos = hdr.payload + hdr.length;
  95. /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
  96. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  97. hdr.class != ASN1_CLASS_UNIVERSAL ||
  98. hdr.tag != ASN1_TAG_OCTETSTRING) {
  99. wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
  100. "(privateKey) - found class %d tag 0x%x",
  101. hdr.class, hdr.tag);
  102. return NULL;
  103. }
  104. wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
  105. return (struct crypto_private_key *)
  106. crypto_rsa_import_private_key(hdr.payload, hdr.length);
  107. }
  108. struct crypto_private_key *
  109. pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
  110. {
  111. struct asn1_hdr hdr;
  112. const u8 *pos, *end, *enc_alg;
  113. size_t enc_alg_len;
  114. u8 *data;
  115. size_t data_len;
  116. if (passwd == NULL)
  117. return NULL;
  118. /*
  119. * PKCS #8, Chapter 7
  120. * EncryptedPrivateKeyInfo ::= SEQUENCE {
  121. * encryptionAlgorithm EncryptionAlgorithmIdentifier,
  122. * encryptedData EncryptedData }
  123. * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
  124. * EncryptedData ::= OCTET STRING
  125. */
  126. if (asn1_get_next(buf, len, &hdr) < 0 ||
  127. hdr.class != ASN1_CLASS_UNIVERSAL ||
  128. hdr.tag != ASN1_TAG_SEQUENCE) {
  129. wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
  130. "header (SEQUENCE); assume encrypted PKCS #8 not "
  131. "used");
  132. return NULL;
  133. }
  134. pos = hdr.payload;
  135. end = pos + hdr.length;
  136. /* encryptionAlgorithm EncryptionAlgorithmIdentifier */
  137. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  138. hdr.class != ASN1_CLASS_UNIVERSAL ||
  139. hdr.tag != ASN1_TAG_SEQUENCE) {
  140. wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
  141. "(AlgorithmIdentifier) - found class %d tag 0x%x; "
  142. "assume encrypted PKCS #8 not used",
  143. hdr.class, hdr.tag);
  144. return NULL;
  145. }
  146. enc_alg = hdr.payload;
  147. enc_alg_len = hdr.length;
  148. pos = hdr.payload + hdr.length;
  149. /* encryptedData EncryptedData */
  150. if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
  151. hdr.class != ASN1_CLASS_UNIVERSAL ||
  152. hdr.tag != ASN1_TAG_OCTETSTRING) {
  153. wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
  154. "(encryptedData) - found class %d tag 0x%x",
  155. hdr.class, hdr.tag);
  156. return NULL;
  157. }
  158. data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
  159. passwd, &data_len);
  160. if (data) {
  161. struct crypto_private_key *key;
  162. key = pkcs8_key_import(data, data_len);
  163. os_free(data);
  164. return key;
  165. }
  166. return NULL;
  167. }