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