PROV: Add DERlib support for ECDSA and EC keys
authorRichard Levitte <levitte@openssl.org>
Tue, 31 Mar 2020 15:20:24 +0000 (17:20 +0200)
committerRichard Levitte <levitte@openssl.org>
Tue, 7 Apr 2020 09:16:56 +0000 (11:16 +0200)
This replaces crypto/ec/ecdsa_aid.c with new code and generated OIDs

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11450)

crypto/ec/build.info
crypto/ec/ecdsa_aid.c [deleted file]
providers/common/der/EC.asn1 [new file with mode: 0644]
providers/common/der/build.info
providers/common/der/der_ec.c.in [new file with mode: 0644]
providers/common/der/der_ec.h.in [new file with mode: 0644]
providers/implementations/signature/build.info
providers/implementations/signature/ecdsa.c

index 4494ce7..8f12e2e 100644 (file)
@@ -51,7 +51,7 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
         ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
         curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
         curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
-        $ECASM ecdsa_aid.c ec_backend.c ecx_backend.c
+        $ECASM ec_backend.c ecx_backend.c
 SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \
                         ec_err.c ecdh_kdf.c eck_prn.c ec_evp_lib.c
 SOURCE[../../providers/libfips.a]=$COMMON
diff --git a/crypto/ec/ecdsa_aid.c b/crypto/ec/ecdsa_aid.c
deleted file mode 100644 (file)
index 01bca40..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <stdlib.h>
-
-#include <openssl/objects.h>
-#include "crypto/ec.h"
-
-#define ASN1_SEQUENCE 0x30
-#define ASN1_OID 0x06
-#define OID_FIRST(a, b) a * 40 + b
-#define DER_840() 0x86, 0x48    /* DER encoding of number 840 is 2 bytes */
-#define DER_10045() 0xCE, 0x3D  /* DER encoding of number 10045 is 2 bytes */
-#define SHA1_SZ 7
-#define SHA2_SZ 8
-#define SHA3_SZ 9
-
-/*
- * -- RFC 3279
- * ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) 10045 }
- * id-ecSigType OBJECT IDENTIFIER ::= { ansi-X9-62 signatures(4) }
- *
- * ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { id-ecSigType 1 }
- */
-#define ENCODE_ALGORITHMIDENTIFIER_SHA1(name)                                  \
-static const unsigned char algorithmidentifier_##name##_der[] = {              \
-    ASN1_SEQUENCE, 2 + SHA1_SZ,                                                \
-    ASN1_OID, SHA1_SZ, OID_FIRST(1, 2), DER_840(), DER_10045(), 4, 1           \
-}
-
-/*
- * -- RFC 5758
- *
- * ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- *      us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 }
- *
- * ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- *      us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
- *
- * ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- *      us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
- *
- * ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
- *      us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
- */
-#define ENCODE_ALGORITHMIDENTIFIER_SHA2(name, n)                               \
-static const unsigned char algorithmidentifier_##name##_der[] = {              \
-    ASN1_SEQUENCE, 2 + SHA2_SZ,                                                \
-    ASN1_OID, SHA2_SZ, OID_FIRST(1, 2), DER_840(), DER_10045(), 4, 3, n        \
-}
-
-/*
- * https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
- *
- * sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
- *
- * id-ecdsa-with-sha3-224 ::= { sigAlgs 9 }
- * id-ecdsa-with-sha3-256 ::= { sigAlgs 10 }
- * id-ecdsa-with-sha3-384 ::= { sigAlgs 11 }
- * id-ecdsa-with-sha3-512 ::= { sigAlgs 12 }
- */
-#define ENCODE_ALGORITHMIDENTIFIER_SHA3(name, n)                               \
-static const unsigned char algorithmidentifier_##name##_der[] = {              \
-    ASN1_SEQUENCE, 2 + SHA3_SZ,                                                \
-    ASN1_OID, SHA3_SZ, OID_FIRST(2, 16), DER_840(), 1, 101, 3, 4, 3, n         \
-}
-
-ENCODE_ALGORITHMIDENTIFIER_SHA1(sha1);
-ENCODE_ALGORITHMIDENTIFIER_SHA2(sha224, 1);
-ENCODE_ALGORITHMIDENTIFIER_SHA2(sha256, 2);
-ENCODE_ALGORITHMIDENTIFIER_SHA2(sha384, 3);
-ENCODE_ALGORITHMIDENTIFIER_SHA2(sha512, 4);
-ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_224, 9);
-ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_256, 10);
-ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_384, 11);
-ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_512, 12);
-/* TODO - Add SHAKE OIDS when they are standardized */
-
-#define MD_CASE(name)                                                   \
-    case NID_##name:                                                    \
-        *len = sizeof(algorithmidentifier_##name##_der);                \
-        return algorithmidentifier_##name##_der
-
-const unsigned char *ecdsa_algorithmidentifier_encoding(int md_nid, size_t *len)
-{
-    switch (md_nid) {
-        MD_CASE(sha1);
-        MD_CASE(sha224);
-        MD_CASE(sha256);
-        MD_CASE(sha384);
-        MD_CASE(sha512);
-        MD_CASE(sha3_224);
-        MD_CASE(sha3_256);
-        MD_CASE(sha3_384);
-        MD_CASE(sha3_512);
-    default:
-        return NULL;
-    }
-}
diff --git a/providers/common/der/EC.asn1 b/providers/common/der/EC.asn1
new file mode 100644 (file)
index 0000000..d55a692
--- /dev/null
@@ -0,0 +1,83 @@
+-- -------------------------------------------------------------------
+-- Taken from RFC 3279, 3  ASN.1 Module
+-- (https://www.rfc-editor.org/rfc/rfc3279.html#section-3)
+
+ansi-X9-62  OBJECT IDENTIFIER ::= {
+     iso(1) member-body(2) us(840) 10045 }
+
+-- Arc for ECDSA signature OIDS
+
+id-ecSigType OBJECT IDENTIFIER ::= { ansi-X9-62 signatures(4) }
+
+-- OID for ECDSA signatures with SHA-1
+
+ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { id-ecSigType 1 }
+
+id-publicKeyType OBJECT IDENTIFIER  ::= { ansi-X9-62 keyType(2) }
+
+id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
+
+-- Named Elliptic Curves in ANSI X9.62.
+
+ellipticCurve OBJECT IDENTIFIER ::= { ansi-X9-62 curves(3) }
+
+c-TwoCurve OBJECT IDENTIFIER ::= {
+     ellipticCurve characteristicTwo(0) }
+
+c2pnb163v1  OBJECT IDENTIFIER  ::=  { c-TwoCurve  1 }
+c2pnb163v2  OBJECT IDENTIFIER  ::=  { c-TwoCurve  2 }
+c2pnb163v3  OBJECT IDENTIFIER  ::=  { c-TwoCurve  3 }
+c2pnb176w1  OBJECT IDENTIFIER  ::=  { c-TwoCurve  4 }
+c2tnb191v1  OBJECT IDENTIFIER  ::=  { c-TwoCurve  5 }
+c2tnb191v2  OBJECT IDENTIFIER  ::=  { c-TwoCurve  6 }
+c2tnb191v3  OBJECT IDENTIFIER  ::=  { c-TwoCurve  7 }
+c2onb191v4  OBJECT IDENTIFIER  ::=  { c-TwoCurve  8 }
+c2onb191v5  OBJECT IDENTIFIER  ::=  { c-TwoCurve  9 }
+c2pnb208w1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 10 }
+c2tnb239v1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 11 }
+c2tnb239v2  OBJECT IDENTIFIER  ::=  { c-TwoCurve 12 }
+c2tnb239v3  OBJECT IDENTIFIER  ::=  { c-TwoCurve 13 }
+c2onb239v4  OBJECT IDENTIFIER  ::=  { c-TwoCurve 14 }
+c2onb239v5  OBJECT IDENTIFIER  ::=  { c-TwoCurve 15 }
+c2pnb272w1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 16 }
+c2pnb304w1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 17 }
+c2tnb359v1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 18 }
+c2pnb368w1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 19 }
+c2tnb431r1  OBJECT IDENTIFIER  ::=  { c-TwoCurve 20 }
+
+primeCurve OBJECT IDENTIFIER ::= { ellipticCurve prime(1) }
+
+prime192v1  OBJECT IDENTIFIER  ::=  { primeCurve  1 }
+prime192v2  OBJECT IDENTIFIER  ::=  { primeCurve  2 }
+prime192v3  OBJECT IDENTIFIER  ::=  { primeCurve  3 }
+prime239v1  OBJECT IDENTIFIER  ::=  { primeCurve  4 }
+prime239v2  OBJECT IDENTIFIER  ::=  { primeCurve  5 }
+prime239v3  OBJECT IDENTIFIER  ::=  { primeCurve  6 }
+prime256v1  OBJECT IDENTIFIER  ::=  { primeCurve  7 }
+
+-- -------------------------------------------------------------------
+-- Taken from RFC 5758, 3.2.  ECDSA Signature Algorithm
+-- (https://www.rfc-editor.org/rfc/rfc5758.html#section-3.2)
+
+ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+     us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 }
+
+ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+     us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
+
+ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+     us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
+
+ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+     us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
+
+-- -------------------------------------------------------------------
+-- Taken from https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
+
+sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
+
+id-ecdsa-with-sha3-224 OBJECT IDENTIFIER ::= { sigAlgs 9 }
+id-ecdsa-with-sha3-256 OBJECT IDENTIFIER ::= { sigAlgs 10 }
+id-ecdsa-with-sha3-384 OBJECT IDENTIFIER ::= { sigAlgs 11 }
+id-ecdsa-with-sha3-512 OBJECT IDENTIFIER ::= { sigAlgs 12 }
+
index c560a70..eda763e 100644 (file)
@@ -1,4 +1,4 @@
-$FIPSABLE=der_rsa.c der_dsa.c
+$FIPSABLE=der_rsa.c der_dsa.c der_ec.c
 
 SOURCE[../../libfips.a]=$FIPSABLE
 SOURCE[../../libnonfips.a]=$FIPSABLE
@@ -16,3 +16,10 @@ DEPEND[der_dsa.c]=oids_to_c.pm
 DEPEND[der_dsa.o]=../include/prov/der_dsa.h
 GENERATE[../include/prov/der_dsa.h]=der_dsa.h.in
 DEPEND[../include/prov/der_dsa.h]=oids_to_c.pm
+
+GENERATE[der_ec.c]=der_ec.c.in
+DEPEND[der_ec.c]=oids_to_c.pm
+
+DEPEND[der_ec.o]=../include/prov/der_ec.h
+GENERATE[../include/prov/der_ec.h]=der_ec.h.in
+DEPEND[../include/prov/der_ec.h]=oids_to_c.pm
diff --git a/providers/common/der/der_ec.c.in b/providers/common/der/der_ec.c.in
new file mode 100644 (file)
index 0000000..a617651
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/bn.h>
+#include <openssl/obj_mac.h>
+#include "prov/der_ec.h"
+
+/* Well known OIDs precompiled */
+{-
+    $OUT = oids_to_c::process_leaves('providers/common/der/EC.asn1',
+                                     { dir => $config{sourcedir},
+                                       filter => \&oids_to_c::filter_to_C });
+-}
+
+int DER_w_algorithmIdentifier_EC(WPACKET *pkt, int cont, EC_KEY *ec)
+{
+    return DER_w_begin_sequence(pkt, cont)
+        /* No parameters (yet?) */
+        && DER_w_precompiled(pkt, -1, der_oid_id_ecPublicKey,
+                             sizeof(der_oid_id_ecPublicKey))
+        && DER_w_end_sequence(pkt, cont);
+}
+
+/* Aliases so we can have a uniform MD_CASE */
+#define der_oid_id_ecdsa_with_sha1   der_oid_ecdsa_with_SHA1
+#define der_oid_id_ecdsa_with_sha224 der_oid_ecdsa_with_SHA224
+#define der_oid_id_ecdsa_with_sha256 der_oid_ecdsa_with_SHA256
+#define der_oid_id_ecdsa_with_sha384 der_oid_ecdsa_with_SHA384
+#define der_oid_id_ecdsa_with_sha512 der_oid_ecdsa_with_SHA512
+
+#define MD_CASE(name)                                                   \
+    case NID_##name:                                                    \
+        precompiled = der_oid_id_ecdsa_with_##name;                     \
+        precompiled_sz = sizeof(der_oid_id_ecdsa_with_##name);          \
+        break;
+
+int DER_w_algorithmIdentifier_ECDSA_with(WPACKET *pkt, int cont,
+                                         EC_KEY *ec, int mdnid)
+{
+    const unsigned char *precompiled = NULL;
+    size_t precompiled_sz = 0;
+
+    switch (mdnid) {
+        MD_CASE(sha1);
+        MD_CASE(sha224);
+        MD_CASE(sha256);
+        MD_CASE(sha384);
+        MD_CASE(sha512);
+        MD_CASE(sha3_224);
+        MD_CASE(sha3_256);
+        MD_CASE(sha3_384);
+        MD_CASE(sha3_512);
+    default:
+        return 0;
+    }
+
+    return DER_w_begin_sequence(pkt, cont)
+        /* No parameters (yet?) */
+        && DER_w_precompiled(pkt, -1, precompiled, precompiled_sz)
+        && DER_w_end_sequence(pkt, cont);
+}
diff --git a/providers/common/der/der_ec.h.in b/providers/common/der/der_ec.h.in
new file mode 100644 (file)
index 0000000..24f153c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/der.h"
+
+/* Well known OIDs precompiled */
+{-
+    $OUT = oids_to_c::process_leaves('providers/common/der/EC.asn1',
+                                     { dir => $config{sourcedir},
+                                       filter => \&oids_to_c::filter_to_H });
+-}
+
+int DER_w_algorithmIdentifier_EC(WPACKET *pkt, int cont, EC_KEY *ec);
+int DER_w_algorithmIdentifier_ECDSA_with(WPACKET *pkt, int cont,
+                                         EC_KEY *ec, int mdnid);
index c536734..dbe0876 100644 (file)
@@ -19,3 +19,4 @@ SOURCE[../../libnonfips.a]=rsa.c
 
 DEPEND[rsa.o]=../../common/include/prov/der_rsa.h
 DEPEND[dsa.o]=../../common/include/prov/der_dsa.h
+DEPEND[ecdsa.o]=../../common/include/prov/der_ec.h
index 733c0a2..e05830f 100644 (file)
 #include <openssl/err.h>
 #include "internal/nelem.h"
 #include "internal/sizes.h"
+#include "internal/cryptlib.h"
 #include "prov/providercommonerr.h"
 #include "prov/implementations.h"
 #include "prov/provider_ctx.h"
 #include "crypto/ec.h"
+#include "prov/der_ec.h"
 
 static OSSL_OP_signature_newctx_fn ecdsa_newctx;
 static OSSL_OP_signature_sign_init_fn ecdsa_signature_init;
@@ -62,7 +64,8 @@ typedef struct {
     char mdname[OSSL_MAX_NAME_SIZE];
 
     /* The Algorithm Identifier of the combined signature algorithm */
-    unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
+    unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
+    unsigned char *aid;
     size_t  aid_len;
     size_t mdsize;
 
@@ -203,8 +206,8 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
                                         const char *props, void *ec)
 {
     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
-    size_t algorithmidentifier_len = 0;
-    const unsigned char *algorithmidentifier;
+    int md_nid = NID_undef;
+    WPACKET pkt;
 
     free_md(ctx);
 
@@ -212,10 +215,7 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
         return 0;
 
     ctx->md = EVP_MD_fetch(ctx->libctx, mdname, props);
-    algorithmidentifier =
-        ecdsa_algorithmidentifier_encoding(get_md_nid(ctx->md),
-                                           &algorithmidentifier_len);
-    if (algorithmidentifier == NULL)
+    if ((md_nid = get_md_nid(ctx->md)) == NID_undef)
         goto error;
 
     ctx->mdsize = EVP_MD_size(ctx->md);
@@ -223,8 +223,21 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
     if (ctx->mdctx == NULL)
         goto error;
 
-    memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
-    ctx->aid_len = algorithmidentifier_len;
+    /*
+     * TODO(3.0) Should we care about DER writing errors?
+     * All it really means is that for some reason, there's no
+     * AlgorithmIdentifier to be had, but the operation itself is
+     * still valid, just as long as it's not used to construct
+     * anything that needs an AlgorithmIdentifier.
+     */
+    ctx->aid_len = 0;
+    if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
+        && DER_w_algorithmIdentifier_ECDSA_with(&pkt, -1, ctx->ec, md_nid)
+        && WPACKET_finish(&pkt)) {
+        WPACKET_get_total_written(&pkt, &ctx->aid_len);
+        ctx->aid = WPACKET_get_curr(&pkt);
+    }
+    WPACKET_cleanup(&pkt);
 
     if (!EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL))
         goto error;