PROV: Add DERlib support for ECDSA and EC keys
[openssl.git] / providers / implementations / signature / ecdsa.c
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;