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