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 19struct 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 || 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 40 /* version Version (Version ::= INTEGER) */ 41 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 42 hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { 43 wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " 44 "class %d tag 0x%x; assume PKCS #8 not used", 45 hdr.class, hdr.tag); 46 return NULL; 47 } 48 49 zero = bignum_init(); 50 if (zero == NULL) 51 return NULL; 52 53 if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { 54 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); 55 bignum_deinit(zero); 56 return NULL; 57 } 58 pos = hdr.payload + hdr.length; 59 60 if (bignum_cmp_d(zero, 0) != 0) { 61 wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " 62 "beginning of private key; not found; assume " 63 "PKCS #8 not used"); 64 bignum_deinit(zero); 65 return NULL; 66 } 67 bignum_deinit(zero); 68 69 /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier 70 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ 71 if (asn1_get_next(pos, len, &hdr) < 0 || 72 hdr.class != ASN1_CLASS_UNIVERSAL || 73 hdr.tag != ASN1_TAG_SEQUENCE) { 74 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " 75 "(AlgorithmIdentifier) - found class %d tag 0x%x; " 76 "assume PKCS #8 not used", 77 hdr.class, hdr.tag); 78 return NULL; 79 } 80 81 if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { 82 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " 83 "(algorithm); assume PKCS #8 not used"); 84 return NULL; 85 } 86 87 asn1_oid_to_str(&oid, obuf, sizeof(obuf)); 88 wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); 89 90 if (oid.len != 7 || 91 oid.oid[0] != 1 /* iso */ || 92 oid.oid[1] != 2 /* member-body */ || 93 oid.oid[2] != 840 /* us */ || 94 oid.oid[3] != 113549 /* rsadsi */ || 95 oid.oid[4] != 1 /* pkcs */ || 96 oid.oid[5] != 1 /* pkcs-1 */ || 97 oid.oid[6] != 1 /* rsaEncryption */) { 98 wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " 99 "algorithm %s", obuf); 100 return NULL; 101 } 102 103 pos = hdr.payload + hdr.length; 104 105 /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ 106 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 107 hdr.class != ASN1_CLASS_UNIVERSAL || 108 hdr.tag != ASN1_TAG_OCTETSTRING) { 109 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " 110 "(privateKey) - found class %d tag 0x%x", 111 hdr.class, hdr.tag); 112 return NULL; 113 } 114 wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); 115 116 return (struct crypto_private_key *) 117 crypto_rsa_import_private_key(hdr.payload, hdr.length); 118} 119 120 121struct crypto_private_key * 122pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) 123{ 124 struct asn1_hdr hdr; 125 const u8 *pos, *end, *enc_alg; 126 size_t enc_alg_len; 127 u8 *data; 128 size_t data_len; 129 130 if (passwd == NULL) 131 return NULL; 132 133 /* 134 * PKCS #8, Chapter 7 135 * EncryptedPrivateKeyInfo ::= SEQUENCE { 136 * encryptionAlgorithm EncryptionAlgorithmIdentifier, 137 * encryptedData EncryptedData } 138 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier 139 * EncryptedData ::= OCTET STRING 140 */ 141 142 if (asn1_get_next(buf, len, &hdr) < 0 || 143 hdr.class != ASN1_CLASS_UNIVERSAL || 144 hdr.tag != ASN1_TAG_SEQUENCE) { 145 wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " 146 "header (SEQUENCE); assume encrypted PKCS #8 not " 147 "used"); 148 return NULL; 149 } 150 pos = hdr.payload; 151 end = pos + hdr.length; 152 153 /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ 154 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 155 hdr.class != ASN1_CLASS_UNIVERSAL || 156 hdr.tag != ASN1_TAG_SEQUENCE) { 157 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " 158 "(AlgorithmIdentifier) - found class %d tag 0x%x; " 159 "assume encrypted PKCS #8 not used", 160 hdr.class, hdr.tag); 161 return NULL; 162 } 163 enc_alg = hdr.payload; 164 enc_alg_len = hdr.length; 165 pos = hdr.payload + hdr.length; 166 167 /* encryptedData EncryptedData */ 168 if (asn1_get_next(pos, end - pos, &hdr) < 0 || 169 hdr.class != ASN1_CLASS_UNIVERSAL || 170 hdr.tag != ASN1_TAG_OCTETSTRING) { 171 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " 172 "(encryptedData) - found class %d tag 0x%x", 173 hdr.class, hdr.tag); 174 return NULL; 175 } 176 177 data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, 178 passwd, &data_len); 179 if (data) { 180 struct crypto_private_key *key; 181 key = pkcs8_key_import(data, data_len); 182 os_free(data); 183 return key; 184 } 185 186 return NULL; 187} 188