diff options
| author | tb <> | 2024-10-28 18:15:53 +0000 | 
|---|---|---|
| committer | tb <> | 2024-10-28 18:15:53 +0000 | 
| commit | c006a5c026da894898b8764743a88da9ed591769 (patch) | |
| tree | 51d722ec88c22fc4d594e194da21676431b2a72a /src | |
| parent | d5d0119ed0fce70c04b0e4f6e89e9f2a1e6b0137 (diff) | |
| download | openbsd-c006a5c026da894898b8764743a88da9ed591769.tar.gz openbsd-c006a5c026da894898b8764743a88da9ed591769.tar.bz2 openbsd-c006a5c026da894898b8764743a88da9ed591769.zip | |
Fix private key encoding in i2d_ECPrivateKey()
The private key is a random integer between 1 and order - 1. As such it
requires at most as many bytes as the order to encode. SEC 1, Section C.4
is very explicit about padding it to this length:
  The component privateKey is the private key defined to be the octet
  string of length [ceil(log_2 n/8)] (where n is the order of the curve)
  obtained from the unsigned integer via the encoding of Section 2.3.7.
Fix this by generalizing a similar fix for field elements.
ok jsing
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/ec/ec_asn1.c | 71 | 
1 files changed, 40 insertions, 31 deletions
| diff --git a/src/lib/libcrypto/ec/ec_asn1.c b/src/lib/libcrypto/ec/ec_asn1.c index d6af3bdec5..45806174d3 100644 --- a/src/lib/libcrypto/ec/ec_asn1.c +++ b/src/lib/libcrypto/ec/ec_asn1.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ec_asn1.c,v 1.92 2024/10/28 18:03:34 tb Exp $ */ | 1 | /* $OpenBSD: ec_asn1.c,v 1.93 2024/10/28 18:15:53 tb Exp $ */ | 
| 2 | /* | 2 | /* | 
| 3 | * Written by Nils Larsch for the OpenSSL project. | 3 | * Written by Nils Larsch for the OpenSSL project. | 
| 4 | */ | 4 | */ | 
| @@ -606,16 +606,12 @@ ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field) | |||
| 606 | } | 606 | } | 
| 607 | 607 | ||
| 608 | static int | 608 | static int | 
| 609 | ec_asn1_encode_field_element(const EC_GROUP *group, const BIGNUM *bn, | 609 | ec_asn1_encode_bn(const EC_GROUP *group, const BIGNUM *bn, int len, | 
| 610 | ASN1_OCTET_STRING *os) | 610 | ASN1_OCTET_STRING *os) | 
| 611 | { | 611 | { | 
| 612 | unsigned char *buf; | 612 | unsigned char *buf; | 
| 613 | int len; | ||
| 614 | int ret = 0; | 613 | int ret = 0; | 
| 615 | 614 | ||
| 616 | /* Zero-pad field element per SEC 1, section 2.3.5. */ | ||
| 617 | len = (EC_GROUP_get_degree(group) + 7) / 8; | ||
| 618 | |||
| 619 | /* One extra byte for historic NUL termination of ASN1_STRINGs. */ | 615 | /* One extra byte for historic NUL termination of ASN1_STRINGs. */ | 
| 620 | if ((buf = calloc(1, len + 1)) == NULL) | 616 | if ((buf = calloc(1, len + 1)) == NULL) | 
| 621 | goto err; | 617 | goto err; | 
| @@ -636,6 +632,32 @@ ec_asn1_encode_field_element(const EC_GROUP *group, const BIGNUM *bn, | |||
| 636 | } | 632 | } | 
| 637 | 633 | ||
| 638 | static int | 634 | static int | 
| 635 | ec_asn1_encode_field_element(const EC_GROUP *group, const BIGNUM *bn, | ||
| 636 | ASN1_OCTET_STRING *os) | ||
| 637 | { | ||
| 638 | int len; | ||
| 639 | |||
| 640 | /* Zero-pad field element to byte length of p per SEC 1, 2.3.5. */ | ||
| 641 | len = (EC_GROUP_get_degree(group) + 7) / 8; | ||
| 642 | return ec_asn1_encode_bn(group, bn, len, os); | ||
| 643 | } | ||
| 644 | |||
| 645 | static int | ||
| 646 | ec_asn1_encode_private_key(const EC_GROUP *group, const BIGNUM *bn, | ||
| 647 | ASN1_OCTET_STRING *os) | ||
| 648 | { | ||
| 649 | const BIGNUM *order; | ||
| 650 | |||
| 651 | if ((order = EC_GROUP_get0_order(group)) == NULL) { | ||
| 652 | ECerror(EC_R_INVALID_GROUP_ORDER); | ||
| 653 | return 0; | ||
| 654 | } | ||
| 655 | |||
| 656 | /* Zero-pad private key to byte length of order per SEC 1, C.4. */ | ||
| 657 | return ec_asn1_encode_bn(group, bn, BN_num_bytes(order), os); | ||
| 658 | } | ||
| 659 | |||
| 660 | static int | ||
| 639 | ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) | 661 | ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve) | 
| 640 | { | 662 | { | 
| 641 | BIGNUM *a = NULL, *b = NULL; | 663 | BIGNUM *a = NULL, *b = NULL; | 
| @@ -1227,7 +1249,7 @@ i2d_ECPrivateKey(EC_KEY *ec_key, unsigned char **out) | |||
| 1227 | { | 1249 | { | 
| 1228 | int ret = 0, ok = 0; | 1250 | int ret = 0, ok = 0; | 
| 1229 | unsigned char *buffer = NULL; | 1251 | unsigned char *buffer = NULL; | 
| 1230 | size_t buf_len = 0, tmp_len; | 1252 | size_t buf_len = 0; | 
| 1231 | EC_PRIVATEKEY *ec_privatekey = NULL; | 1253 | EC_PRIVATEKEY *ec_privatekey = NULL; | 
| 1232 | 1254 | ||
| 1233 | if (ec_key == NULL || ec_key->group == NULL || ec_key->priv_key == NULL || | 1255 | if (ec_key == NULL || ec_key->group == NULL || ec_key->priv_key == NULL || | 
| @@ -1241,20 +1263,9 @@ i2d_ECPrivateKey(EC_KEY *ec_key, unsigned char **out) | |||
| 1241 | } | 1263 | } | 
| 1242 | ec_privatekey->version = ec_key->version; | 1264 | ec_privatekey->version = ec_key->version; | 
| 1243 | 1265 | ||
| 1244 | buf_len = (size_t) BN_num_bytes(ec_key->priv_key); | 1266 | if (!ec_asn1_encode_private_key(ec_key->group, ec_key->priv_key, | 
| 1245 | buffer = malloc(buf_len); | 1267 | ec_privatekey->privateKey)) | 
| 1246 | if (buffer == NULL) { | ||
| 1247 | ECerror(ERR_R_MALLOC_FAILURE); | ||
| 1248 | goto err; | ||
| 1249 | } | ||
| 1250 | if (!BN_bn2bin(ec_key->priv_key, buffer)) { | ||
| 1251 | ECerror(ERR_R_BN_LIB); | ||
| 1252 | goto err; | ||
| 1253 | } | ||
| 1254 | if (!ASN1_STRING_set(ec_privatekey->privateKey, buffer, buf_len)) { | ||
| 1255 | ECerror(ERR_R_ASN1_LIB); | ||
| 1256 | goto err; | 1268 | goto err; | 
| 1257 | } | ||
| 1258 | if (!(ec_key->enc_flag & EC_PKEY_NO_PARAMETERS)) { | 1269 | if (!(ec_key->enc_flag & EC_PKEY_NO_PARAMETERS)) { | 
| 1259 | ECPKPARAMETERS *parameters; | 1270 | ECPKPARAMETERS *parameters; | 
| 1260 | 1271 | ||
| @@ -1270,17 +1281,15 @@ i2d_ECPrivateKey(EC_KEY *ec_key, unsigned char **out) | |||
| 1270 | ECerror(ERR_R_MALLOC_FAILURE); | 1281 | ECerror(ERR_R_MALLOC_FAILURE); | 
| 1271 | goto err; | 1282 | goto err; | 
| 1272 | } | 1283 | } | 
| 1273 | tmp_len = EC_POINT_point2oct(ec_key->group, ec_key->pub_key, | 1284 | if ((buf_len = EC_POINT_point2oct(ec_key->group, ec_key->pub_key, | 
| 1274 | ec_key->conv_form, NULL, 0, NULL); | 1285 | ec_key->conv_form, NULL, 0, NULL)) == 0) { | 
| 1275 | 1286 | ECerror(ERR_R_EC_LIB); | |
| 1276 | if (tmp_len > buf_len) { | 1287 | goto err; | 
| 1277 | unsigned char *tmp_buffer = realloc(buffer, tmp_len); | 1288 | } | 
| 1278 | if (!tmp_buffer) { | 1289 | |
| 1279 | ECerror(ERR_R_MALLOC_FAILURE); | 1290 | if ((buffer = calloc(1, buf_len)) == NULL) { | 
| 1280 | goto err; | 1291 | ECerror(ERR_R_MALLOC_FAILURE); | 
| 1281 | } | 1292 | goto err; | 
| 1282 | buffer = tmp_buffer; | ||
| 1283 | buf_len = tmp_len; | ||
| 1284 | } | 1293 | } | 
| 1285 | if (!EC_POINT_point2oct(ec_key->group, ec_key->pub_key, | 1294 | if (!EC_POINT_point2oct(ec_key->group, ec_key->pub_key, | 
| 1286 | ec_key->conv_form, buffer, buf_len, NULL)) { | 1295 | ec_key->conv_form, buffer, buf_len, NULL)) { | 
