Skip to content

Commit d8c6c0e

Browse files
davidbennebeid
authored andcommitted
Set an EVP_PKEY's algorithm and data together
Cherry-picked from BoringSSL b0ef87e5e3ba9a4f4b5bba4434f6f2e630507b48. Replace evp_pkey_set_method with evp_pkey_set0, which sets both the method and key data together, avoiding half-initialized EVP_PKEY states. Adapted for AWS-LC: - RSA/DSA/EC_KEY/DH assign functions and EVP_PKEY_new_raw_* are in different files than BoringSSL (FIPS module vs evp_extra) - AWS-LC has a pkey.type field that must also be set (BoringSSL derives type from ameth) - ed25519/x25519 set_priv_raw/set_pub_raw callbacks are shared with ed25519ph (AWS-LC specific), so callers (EVP_PKEY_new_raw_*, evp_asn1 decode) set the method via evp_pkey_set0 before invoking the callback, rather than having the callback set it - KEM and PQDSA (AWS-LC specific) updated to create key first, then call evp_pkey_set0 with method+data together
1 parent 243c976 commit d8c6c0e

File tree

8 files changed

+40
-56
lines changed

8 files changed

+40
-56
lines changed

crypto/evp_extra/evp_asn1.c

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -130,31 +130,25 @@ EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
130130
CBS oid;
131131

132132
const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm, &oid);
133-
if (method == NULL) {
133+
if (method == NULL || method->pub_decode == NULL) {
134134
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
135135
return NULL;
136136
}
137-
if (// Every key type defined encodes the key as a byte string with the same
138-
// conversion to BIT STRING.
139-
!CBS_get_u8(&key, &padding) ||
137+
// Every key type defined encodes the key as a byte string with the same
138+
// conversion to BIT STRING, so perform that common conversion ahead of time.
139+
if (!CBS_get_u8(&key, &padding) ||
140140
padding != 0) {
141141
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
142142
return NULL;
143143
}
144144

145-
// Set up an |EVP_PKEY| of the appropriate type.
146145
EVP_PKEY *ret = EVP_PKEY_new();
147146
if (ret == NULL) {
148147
goto err;
149148
}
150-
evp_pkey_set_method(ret, method);
149+
evp_pkey_set0(ret, method, NULL);
151150

152-
// Call into the type-specific SPKI decoding function.
153-
if (ret->ameth->pub_decode == NULL) {
154-
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
155-
goto err;
156-
}
157-
if (!ret->ameth->pub_decode(ret, &oid, &algorithm, &key)) {
151+
if (!method->pub_decode(ret, &oid, &algorithm, &key)) {
158152
goto err;
159153
}
160154

@@ -198,7 +192,7 @@ EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
198192
CBS oid;
199193

200194
const EVP_PKEY_ASN1_METHOD *method = parse_key_type(&algorithm, &oid);
201-
if (method == NULL) {
195+
if (method == NULL || method->priv_decode == NULL) {
202196
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
203197
return NULL;
204198
}
@@ -230,16 +224,10 @@ EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
230224
if (ret == NULL) {
231225
goto err;
232226
}
233-
evp_pkey_set_method(ret, method);
234-
235-
// Call into the type-specific PrivateKeyInfo decoding function.
236-
if (ret->ameth->priv_decode == NULL) {
237-
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
238-
goto err;
239-
}
227+
evp_pkey_set0(ret, method, NULL);
240228

241-
if (!ret->ameth->priv_decode(ret, &oid, &algorithm, &key,
242-
has_pub ? &public_key : NULL)) {
229+
if (!method->priv_decode(ret, &oid, &algorithm, &key,
230+
has_pub ? &public_key : NULL)) {
243231
goto err;
244232
}
245233

crypto/evp_extra/internal.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ extern const EVP_PKEY_METHOD dh_pkey_meth;
4141
extern const EVP_PKEY_METHOD dsa_pkey_meth;
4242
extern const EVP_PKEY_METHOD pqdsa_pkey_meth;
4343

44-
// evp_pkey_set_method behaves like |EVP_PKEY_set_type|, but takes a pointer to
45-
// a method table. This avoids depending on every |EVP_PKEY_ASN1_METHOD|.
46-
void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method);
44+
// evp_pkey_set0 sets |pkey|'s method to |method| and data to |pkey_data|,
45+
// freeing any key that may previously have been configured. This function takes
46+
// ownership of |pkey_data|, which must be of the type expected by |method|.
47+
void evp_pkey_set0(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method,
48+
void *pkey_data);
4749

4850
// Returns a reference to the list |non_fips_pkey_evp_methods|. The list has
4951
// size |NON_FIPS_EVP_PKEY_METHODS|.

crypto/evp_extra/p_dh_asn1.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
174174
if (key == NULL) {
175175
return 0;
176176
}
177-
evp_pkey_set_method(pkey, &dh_asn1_meth);
178-
pkey->pkey.dh = key;
177+
evp_pkey_set0(pkey, &dh_asn1_meth, key);
179178
return 1;
180179
}
181180

crypto/evp_extra/p_x25519.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,10 @@ static int pkey_x25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
3131
return 0;
3232
}
3333

34-
evp_pkey_set_method(pkey, &x25519_asn1_meth);
35-
3634
X25519_keypair(key->pub, key->priv);
3735
key->has_private = 1;
3836

39-
OPENSSL_free(pkey->pkey.ptr);
40-
pkey->pkey.ptr = key;
37+
evp_pkey_set0(pkey, &x25519_asn1_meth, key);
4138
return 1;
4239
}
4340

crypto/fipsmodule/evp/evp.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,11 @@ int EVP_read_pw_string_min(char *buf, int min_length, int length,
236236
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
237237
SET_DIT_AUTO_RESET;
238238
if (to->type == EVP_PKEY_NONE) {
239-
evp_pkey_set_method(to, from->ameth);
239+
// TODO(crbug.com/42290409): This shouldn't leave |to| in a half-empty state
240+
// on error. The complexity here largely comes from parameterless DSA keys,
241+
// which we no longer support, so this function can probably be trimmed
242+
// down.
243+
evp_pkey_set0(to, from->ameth, NULL);
240244
} else if (to->type != from->type) {
241245
OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
242246
return 0;
@@ -346,18 +350,20 @@ static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
346350
return NULL;
347351
}
348352

349-
void evp_pkey_set_method(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method) {
353+
void evp_pkey_set0(EVP_PKEY *pkey, const EVP_PKEY_ASN1_METHOD *method,
354+
void *pkey_data) {
350355
free_it(pkey);
351356
pkey->ameth = method;
352-
pkey->type = pkey->ameth->pkey_id;
357+
pkey->type = method ? method->pkey_id : EVP_PKEY_NONE;
358+
pkey->pkey.ptr = pkey_data;
353359
}
354360

355361
static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len) {
356362
if (pkey && pkey->pkey.ptr) {
357363
// This isn't strictly necessary, but historically |EVP_PKEY_set_type| would
358364
// clear |pkey| even if |evp_pkey_asn1_find| failed, so we preserve that
359365
// behavior.
360-
free_it(pkey);
366+
evp_pkey_set0(pkey, NULL, NULL);
361367
}
362368

363369
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
@@ -375,7 +381,7 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len) {
375381
}
376382

377383
if (pkey) {
378-
evp_pkey_set_method(pkey, ameth);
384+
evp_pkey_set0(pkey, ameth, NULL);
379385
}
380386

381387
return 1;
@@ -446,8 +452,7 @@ int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) {
446452
}
447453
const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(EVP_PKEY_RSA);
448454
assert(meth != NULL);
449-
evp_pkey_set_method(pkey, meth);
450-
pkey->pkey.ptr = key;
455+
evp_pkey_set0(pkey, meth, key);
451456
return 1;
452457
}
453458

@@ -485,8 +490,7 @@ int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) {
485490
}
486491
const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(EVP_PKEY_DSA);
487492
assert(meth != NULL);
488-
evp_pkey_set_method(pkey, meth);
489-
pkey->pkey.ptr = key;
493+
evp_pkey_set0(pkey, meth, key);
490494
return 1;
491495
}
492496

@@ -524,8 +528,7 @@ int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
524528
}
525529
const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(EVP_PKEY_EC);
526530
assert(meth != NULL);
527-
evp_pkey_set_method(pkey, meth);
528-
pkey->pkey.ptr = key;
531+
evp_pkey_set0(pkey, meth, key);
529532
return 1;
530533
}
531534

@@ -608,9 +611,9 @@ EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *unused,
608611
if (ret == NULL) {
609612
goto err;
610613
}
611-
evp_pkey_set_method(ret, method);
614+
evp_pkey_set0(ret, method, NULL);
612615

613-
if (!ret->ameth->set_priv_raw(ret, in, len, NULL, 0)) {
616+
if (!method->set_priv_raw(ret, in, len, NULL, 0)) {
614617
goto err;
615618
}
616619

@@ -645,9 +648,9 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *unused,
645648
if (ret == NULL) {
646649
goto err;
647650
}
648-
evp_pkey_set_method(ret, method);
651+
evp_pkey_set0(ret, method, NULL);
649652

650-
if (!ret->ameth->set_pub_raw(ret, in, len)) {
653+
if (!method->set_pub_raw(ret, in, len)) {
651654
goto err;
652655
}
653656

crypto/fipsmodule/evp/p_ed25519.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,13 @@ static int pkey_ed25519_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
3131
return 0;
3232
}
3333

34-
evp_pkey_set_method(pkey, &ed25519_asn1_meth);
35-
3634
uint8_t pubkey_unused[32];
3735
int result = ED25519_keypair_internal(pubkey_unused, key->key);
3836
if (result) {
3937
key->has_private = 1;
40-
OPENSSL_free(pkey->pkey.ptr);
41-
pkey->pkey.ptr = key;
38+
evp_pkey_set0(pkey, &ed25519_asn1_meth, key);
39+
} else {
40+
OPENSSL_free(key);
4241
}
4342

4443
return result;

crypto/fipsmodule/evp/p_kem.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,16 +366,14 @@ int EVP_PKEY_kem_set_params(EVP_PKEY *pkey, int nid) {
366366
return 0;
367367
}
368368

369-
evp_pkey_set_method(pkey, &kem_asn1_meth);
370-
371369
KEM_KEY *key = KEM_KEY_new();
372370
if (key == NULL) {
373371
// KEM_KEY_new sets the appropriate error.
374372
return 0;
375373
}
376374

377375
key->kem = kem;
378-
pkey->pkey.kem_key = key;
376+
evp_pkey_set0(pkey, &kem_asn1_meth, key);
379377

380378
return 1;
381379
}

crypto/fipsmodule/evp/p_pqdsa.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,16 +225,14 @@ int EVP_PKEY_pqdsa_set_params(EVP_PKEY *pkey, int nid) {
225225
return 0;
226226
}
227227

228-
evp_pkey_set_method(pkey, &pqdsa_asn1_meth);
229-
230228
PQDSA_KEY *key = PQDSA_KEY_new();
231229
if (key == NULL) {
232230
// PQDSA_KEY_new sets the appropriate error.
233231
return 0;
234232
}
235233

236234
key->pqdsa = pqdsa;
237-
pkey->pkey.pqdsa_key = key;
235+
evp_pkey_set0(pkey, &pqdsa_asn1_meth, key);
238236

239237
return 1;
240238
}

0 commit comments

Comments
 (0)