diff options
author | David Benjamin <davidben@chromium.org> | 2015-12-31 05:40:40 +0300 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2016-02-17 19:28:07 +0300 |
commit | 68772b31b07827793827e45ea81e8035269774c1 (patch) | |
tree | f9f661c29a375dfd4586e847b2a5ece92733de5f /crypto/evp/p_rsa_asn1.c | |
parent | 2dc469e06655be3a761ee25b1d89b4f6ebfc29a4 (diff) |
Implement new SPKI parsers.
Many consumers need SPKI support (X.509, TLS, QUIC, WebCrypto), each
with different ways to set signature parameters. SPKIs themselves can
get complex with id-RSASSA-PSS keys which come with various constraints
in the key parameters. This suggests we want a common in-library
representation of an SPKI.
This adds two new functions EVP_parse_public_key and
EVP_marshal_public_key which converts EVP_PKEY to and from SPKI and
implements X509_PUBKEY functions with them. EVP_PKEY seems to have been
intended to be able to express the supported SPKI types with
full-fidelity, so these APIs will continue this.
This means future support for id-RSASSA-PSS would *not* repurpose
EVP_PKEY_RSA. I'm worried about code assuming EVP_PKEY_RSA implies
acting on the RSA* is legal. Instead, it'd add an EVP_PKEY_RSA_PSS and
the data pointer would be some (exposed, so the caller may still check
key size, etc.) RSA_PSS_KEY struct. Internally, the EVP_PKEY_CTX
implementation would enforce the key constraints. If RSA_PSS_KEY would
later need its own API, that code would move there, but that seems
unlikely.
Ideally we'd have a 1:1 correspondence with key OID, although we may
have to fudge things if mistakes happen in standardization. (Whether or
not X.509 reuses id-ecPublicKey for Ed25519, we'll give it a separate
EVP_PKEY type.)
DSA parsing hooks are still implemented, missing parameters and all for
now. This isn't any worse than before.
Decoupling from the giant crypto/obj OID table will be a later task.
BUG=522228
Change-Id: I0e3964edf20cb795a18b0991d17e5ca8bce3e28c
Reviewed-on: https://boringssl-review.googlesource.com/6861
Reviewed-by: Adam Langley <agl@google.com>
Diffstat (limited to 'crypto/evp/p_rsa_asn1.c')
-rw-r--r-- | crypto/evp/p_rsa_asn1.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c index 70f0b763..83da7df4 100644 --- a/crypto/evp/p_rsa_asn1.c +++ b/crypto/evp/p_rsa_asn1.c @@ -69,26 +69,33 @@ #include "internal.h" -static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { - uint8_t *encoded; - size_t encoded_len; - if (!RSA_public_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) { - return 0; - } - - if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL, - encoded, encoded_len)) { - OPENSSL_free(encoded); +static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) { + /* See RFC 3279, section 2.3.1. */ + CBB spki, algorithm, null, key_bitstring; + if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) || + !OBJ_nid2cbb(&algorithm, NID_rsaEncryption) || + !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) || + !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&key_bitstring, 0 /* padding */) || + !RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) || + !CBB_flush(out)) { + OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR); return 0; } return 1; } -static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { - const uint8_t *p; - int pklen; - if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) { +static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) { + /* See RFC 3279, section 2.3.1. */ + + /* The parameters must be NULL. */ + CBS null; + if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) || + CBS_len(&null) != 0 || + CBS_len(params) != 0) { + OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); return 0; } @@ -98,16 +105,14 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { * TODO(davidben): Switch this to the strict version in March 2016 or when * Chromium can force client certificates down a different codepath, whichever * comes first. */ - CBS cbs; - CBS_init(&cbs, p, pklen); - RSA *rsa = RSA_parse_public_key_buggy(&cbs); - if (rsa == NULL || CBS_len(&cbs) != 0) { + RSA *rsa = RSA_parse_public_key_buggy(key); + if (rsa == NULL || CBS_len(key) != 0) { OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR); RSA_free(rsa); return 0; } - EVP_PKEY_assign_RSA(pkey, rsa); + EVP_PKEY_assign_RSA(out, rsa); return 1; } |