summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/curve25519/curve25519_public_key.c
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@debian.org>2019-01-02 10:45:36 +0100
committerYves-Alexis Perez <corsac@debian.org>2019-01-02 11:07:05 +0100
commit918094fde55fa0dbfd59a5f88d576efb513a88db (patch)
tree61e31656c60a6cc928c50cd633568043673e2cbd /src/libstrongswan/plugins/curve25519/curve25519_public_key.c
parent69bc96f6b0b388d35e983f8d27224fa49d92918c (diff)
downloadvyos-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.c110
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;