diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2019-01-02 10:45:36 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2019-01-02 11:07:05 +0100 |
commit | 918094fde55fa0dbfd59a5f88d576efb513a88db (patch) | |
tree | 61e31656c60a6cc928c50cd633568043673e2cbd /src/libstrongswan/plugins/curve25519/curve25519_public_key.c | |
parent | 69bc96f6b0b388d35e983f8d27224fa49d92918c (diff) | |
download | vyos-strongswan-918094fde55fa0dbfd59a5f88d576efb513a88db.tar.gz vyos-strongswan-918094fde55fa0dbfd59a5f88d576efb513a88db.zip |
New upstream version 5.7.2
Diffstat (limited to 'src/libstrongswan/plugins/curve25519/curve25519_public_key.c')
-rw-r--r-- | src/libstrongswan/plugins/curve25519/curve25519_public_key.c | 110 |
1 files changed, 75 insertions, 35 deletions
diff --git a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c index 1d4dec565..dfc1df4d0 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2018 Tobias Brunner * Copyright (C) 2016 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -48,6 +49,13 @@ METHOD(public_key_t, get_type, key_type_t, return KEY_ED25519; } +/* L = 2^252+27742317777372353535851937790883648493 in little-endian form */ +static chunk_t curve25519_order = chunk_from_chars( + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10); + METHOD(public_key_t, verify, bool, private_curve25519_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t signature) @@ -93,6 +101,20 @@ METHOD(public_key_t, verify, bool, { return FALSE; } + /* make sure 0 <= s < L, as per RFC 8032, section 5.1.7 to prevent signature + * malleability. Due to the three-bit check above (forces s < 2^253) there + * is not that much room, but adding L once works with most signatures */ + for (i = 31; ; i--) + { + if (sig[i+32] < curve25519_order.ptr[i]) + { + break; + } + else if (sig[i+32] > curve25519_order.ptr[i] || i == 0) + { + return FALSE; + } + } hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); if (!hasher) @@ -200,22 +222,68 @@ static const asn1Object_t pubkeyObjects[] = { #define ED25519_SUBJECT_PUBLIC_KEY 2 /** + * Parse the ASN.1-encoded subjectPublicKeyInfo + */ +static bool parse_public_key_info(private_curve25519_public_key_t *this, + chunk_t blob) +{ + asn1_parser_t *parser; + chunk_t object; + bool success = FALSE; + int objectID, oid; + + parser = asn1_parser_create(pubkeyObjects, blob); + + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM: + { + oid = asn1_parse_algorithmIdentifier(object, + parser->get_level(parser) + 1, NULL); + if (oid != OID_ED25519) + { + goto end; + } + break; + } + case ED25519_SUBJECT_PUBLIC_KEY: + { + /* encoded as an ASN1 BIT STRING */ + if (object.len != 1 + ED25519_KEY_LEN) + { + goto end; + } + this->pubkey = chunk_clone(chunk_skip(object, 1)); + break; + } + } + } + success = parser->success(parser); + +end: + parser->destroy(parser); + return success; +} + +/** * See header. */ curve25519_public_key_t *curve25519_public_key_load(key_type_t type, va_list args) { private_curve25519_public_key_t *this; - chunk_t blob = chunk_empty, object; - asn1_parser_t *parser; - bool success = FALSE; - int objectID, oid; + chunk_t asn1 = chunk_empty, blob = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) { case BUILD_BLOB_ASN1_DER: + asn1 = va_arg(args, chunk_t); + continue; + case BUILD_EDDSA_PUB: blob = va_arg(args, chunk_t); continue; case BUILD_END: @@ -244,39 +312,11 @@ curve25519_public_key_t *curve25519_public_key_load(key_type_t type, .ref = 1, ); - parser = asn1_parser_create(pubkeyObjects, blob); - - while (parser->iterate(parser, &objectID, &object)) + if (blob.len == ED25519_KEY_LEN) { - switch (objectID) - { - case ED25519_SUBJECT_PUBLIC_KEY_ALGORITHM: - { - oid = asn1_parse_algorithmIdentifier(object, - parser->get_level(parser) + 1, NULL); - if (oid != OID_ED25519) - { - goto end; - } - break; - } - case ED25519_SUBJECT_PUBLIC_KEY: - { - /* encoded as an ASN1 BIT STRING */ - if (object.len != 1 + ED25519_KEY_LEN) - { - goto end; - } - this->pubkey = chunk_clone(chunk_skip(object, 1)); - break; - } - } + this->pubkey = chunk_clone(blob); } - success = parser->success(parser); - -end: - parser->destroy(parser); - if (!success) + else if (!asn1.len || !parse_public_key_info(this, asn1)) { destroy(this); return NULL; |