Internal TLS: Added support for parsing PKCS #8 formatted private keys
The internal TLS implementation can now use both PKCS #1 RSA private key and PKCS #8 encapsulated RSA private key. PKCS #8 encrypted private key is not yet supported.
This commit is contained in:
parent
b5aebee49e
commit
d952d16df4
2 changed files with 117 additions and 0 deletions
|
@ -22,6 +22,7 @@
|
|||
#include "aes.h"
|
||||
#include "tls/rsa.h"
|
||||
#include "tls/bignum.h"
|
||||
#include "tls/asn1.h"
|
||||
|
||||
|
||||
#ifdef EAP_TLS_FUNCS
|
||||
|
@ -434,9 +435,122 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len)
|
|||
}
|
||||
|
||||
|
||||
static struct crypto_private_key *
|
||||
crypto_pkcs8_key_import(const u8 *buf, size_t len)
|
||||
{
|
||||
struct asn1_hdr hdr;
|
||||
const u8 *pos, *end;
|
||||
struct bignum *zero;
|
||||
struct asn1_oid oid;
|
||||
char obuf[80];
|
||||
|
||||
/* PKCS #8, Chapter 6 */
|
||||
|
||||
/* PrivateKeyInfo ::= SEQUENCE */
|
||||
if (asn1_get_next(buf, len, &hdr) < 0 ||
|
||||
hdr.class != ASN1_CLASS_UNIVERSAL ||
|
||||
hdr.tag != ASN1_TAG_SEQUENCE) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
|
||||
"header (SEQUENCE); assume PKCS #8 not used");
|
||||
return NULL;
|
||||
}
|
||||
pos = hdr.payload;
|
||||
end = pos + hdr.length;
|
||||
|
||||
/* version Version (Version ::= INTEGER) */
|
||||
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
|
||||
hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
|
||||
"class %d tag 0x%x; assume PKCS #8 not used",
|
||||
hdr.class, hdr.tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
zero = bignum_init();
|
||||
if (zero == NULL)
|
||||
return NULL;
|
||||
|
||||
if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
|
||||
bignum_deinit(zero);
|
||||
return NULL;
|
||||
}
|
||||
pos = hdr.payload + hdr.length;
|
||||
|
||||
if (bignum_cmp_d(zero, 0) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
|
||||
"beginning of private key; not found; assume "
|
||||
"PKCS #8 not used");
|
||||
bignum_deinit(zero);
|
||||
return NULL;
|
||||
}
|
||||
bignum_deinit(zero);
|
||||
|
||||
/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
|
||||
* (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
|
||||
if (asn1_get_next(pos, len, &hdr) < 0 ||
|
||||
hdr.class != ASN1_CLASS_UNIVERSAL ||
|
||||
hdr.tag != ASN1_TAG_SEQUENCE) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
|
||||
"(AlgorithmIdentifier) - found class %d tag 0x%x; "
|
||||
"assume PKCS #8 not used",
|
||||
hdr.class, hdr.tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
|
||||
"(algorithm); assume PKCS #8 not used");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
asn1_oid_to_str(&oid, obuf, sizeof(obuf));
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
|
||||
|
||||
if (oid.len != 7 ||
|
||||
oid.oid[0] != 1 /* iso */ ||
|
||||
oid.oid[1] != 2 /* member-body */ ||
|
||||
oid.oid[2] != 840 /* us */ ||
|
||||
oid.oid[3] != 113549 /* rsadsi */ ||
|
||||
oid.oid[4] != 1 /* pkcs */ ||
|
||||
oid.oid[5] != 1 /* pkcs-1 */ ||
|
||||
oid.oid[6] != 1 /* rsaEncryption */) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
|
||||
"algorithm %s", obuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pos = hdr.payload + hdr.length;
|
||||
|
||||
/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
|
||||
if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
|
||||
hdr.class != ASN1_CLASS_UNIVERSAL ||
|
||||
hdr.tag != ASN1_TAG_OCTETSTRING) {
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
|
||||
"(privateKey) - found class %d tag 0x%x",
|
||||
hdr.class, hdr.tag);
|
||||
return NULL;
|
||||
}
|
||||
wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
|
||||
|
||||
return (struct crypto_private_key *)
|
||||
crypto_rsa_import_private_key(hdr.payload, hdr.length);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len)
|
||||
{
|
||||
struct crypto_private_key *res;
|
||||
|
||||
/* First, check for possible PKCS #8 encoding */
|
||||
res = crypto_pkcs8_key_import(key, len);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
|
||||
wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
|
||||
"key");
|
||||
return (struct crypto_private_key *)
|
||||
crypto_rsa_import_private_key(key, len);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ ChangeLog for wpa_supplicant
|
|||
* fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to
|
||||
allow fallback to full handshake if server rejects PAC-Opaque
|
||||
* added fragmentation support for EAP-TNC
|
||||
* added support for parsing PKCS #8 formatted private keys into the
|
||||
internal TLS implementation (both PKCS #1 RSA key and PKCS #8
|
||||
encapsulated RSA key can now be used)
|
||||
|
||||
2008-02-22 - v0.6.3
|
||||
* removed 'nai' and 'eappsk' network configuration variables that were
|
||||
|
|
Loading…
Reference in a new issue