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/lib | |
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/lib')
-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)) { |