1*a5aac4c5Stb /* $OpenBSD: dsa_pmeth.c,v 1.21 2024/10/19 14:39:44 tb Exp $ */ 2f1535dc8Sdjm /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3f1535dc8Sdjm * project 2006. 4f1535dc8Sdjm */ 5f1535dc8Sdjm /* ==================================================================== 6f1535dc8Sdjm * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7f1535dc8Sdjm * 8f1535dc8Sdjm * Redistribution and use in source and binary forms, with or without 9f1535dc8Sdjm * modification, are permitted provided that the following conditions 10f1535dc8Sdjm * are met: 11f1535dc8Sdjm * 12f1535dc8Sdjm * 1. Redistributions of source code must retain the above copyright 13f1535dc8Sdjm * notice, this list of conditions and the following disclaimer. 14f1535dc8Sdjm * 15f1535dc8Sdjm * 2. Redistributions in binary form must reproduce the above copyright 16f1535dc8Sdjm * notice, this list of conditions and the following disclaimer in 17f1535dc8Sdjm * the documentation and/or other materials provided with the 18f1535dc8Sdjm * distribution. 19f1535dc8Sdjm * 20f1535dc8Sdjm * 3. All advertising materials mentioning features or use of this 21f1535dc8Sdjm * software must display the following acknowledgment: 22f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project 23f1535dc8Sdjm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24f1535dc8Sdjm * 25f1535dc8Sdjm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26f1535dc8Sdjm * endorse or promote products derived from this software without 27f1535dc8Sdjm * prior written permission. For written permission, please contact 28f1535dc8Sdjm * licensing@OpenSSL.org. 29f1535dc8Sdjm * 30f1535dc8Sdjm * 5. Products derived from this software may not be called "OpenSSL" 31f1535dc8Sdjm * nor may "OpenSSL" appear in their names without prior written 32f1535dc8Sdjm * permission of the OpenSSL Project. 33f1535dc8Sdjm * 34f1535dc8Sdjm * 6. Redistributions of any form whatsoever must retain the following 35f1535dc8Sdjm * acknowledgment: 36f1535dc8Sdjm * "This product includes software developed by the OpenSSL Project 37f1535dc8Sdjm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38f1535dc8Sdjm * 39f1535dc8Sdjm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40f1535dc8Sdjm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41f1535dc8Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42f1535dc8Sdjm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43f1535dc8Sdjm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44f1535dc8Sdjm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45f1535dc8Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46f1535dc8Sdjm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47f1535dc8Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48f1535dc8Sdjm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49f1535dc8Sdjm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50f1535dc8Sdjm * OF THE POSSIBILITY OF SUCH DAMAGE. 51f1535dc8Sdjm * ==================================================================== 52f1535dc8Sdjm * 53f1535dc8Sdjm * This product includes cryptographic software written by Eric Young 54f1535dc8Sdjm * (eay@cryptsoft.com). This product includes software written by Tim 55f1535dc8Sdjm * Hudson (tjh@cryptsoft.com). 56f1535dc8Sdjm * 57f1535dc8Sdjm */ 58f1535dc8Sdjm 59b1d57841Sderaadt #include <limits.h> 60a8913c44Sjsing #include <stdio.h> 611e10d066Sop #include <stdlib.h> 62a8913c44Sjsing #include <string.h> 63a8913c44Sjsing 64f1535dc8Sdjm #include <openssl/asn1t.h> 65f1535dc8Sdjm #include <openssl/bn.h> 66b6ab114eSjsing #include <openssl/err.h> 67b6ab114eSjsing #include <openssl/evp.h> 68b6ab114eSjsing #include <openssl/x509.h> 69b6ab114eSjsing 70c9675a23Stb #include "bn_local.h" 71c9675a23Stb #include "dsa_local.h" 72c9675a23Stb #include "evp_local.h" 73f1535dc8Sdjm 74f1535dc8Sdjm /* DSA pkey context structure */ 75f1535dc8Sdjm 76e85b1b81Smiod typedef struct { 77f1535dc8Sdjm /* Parameter gen parameters */ 78f1535dc8Sdjm int nbits; /* size of p in bits (default: 1024) */ 79f1535dc8Sdjm int qbits; /* size of q in bits (default: 160) */ 80f1535dc8Sdjm const EVP_MD *pmd; /* MD for parameter generation */ 81f1535dc8Sdjm /* Keygen callback info */ 82f1535dc8Sdjm int gentmp[2]; 83f1535dc8Sdjm /* message digest */ 84f1535dc8Sdjm const EVP_MD *md; /* MD for the signature */ 85f1535dc8Sdjm } DSA_PKEY_CTX; 86f1535dc8Sdjm 87e85b1b81Smiod static int 88e85b1b81Smiod pkey_dsa_init(EVP_PKEY_CTX *ctx) 89f1535dc8Sdjm { 90f1535dc8Sdjm DSA_PKEY_CTX *dctx; 91e85b1b81Smiod 926f3a6cb1Sbeck dctx = malloc(sizeof(DSA_PKEY_CTX)); 93f1535dc8Sdjm if (!dctx) 94f1535dc8Sdjm return 0; 95f1535dc8Sdjm dctx->nbits = 1024; 96f1535dc8Sdjm dctx->qbits = 160; 97f1535dc8Sdjm dctx->pmd = NULL; 98f1535dc8Sdjm dctx->md = NULL; 99f1535dc8Sdjm 100f1535dc8Sdjm ctx->data = dctx; 101f1535dc8Sdjm ctx->keygen_info = dctx->gentmp; 102f1535dc8Sdjm ctx->keygen_info_count = 2; 103f1535dc8Sdjm 104f1535dc8Sdjm return 1; 105f1535dc8Sdjm } 106f1535dc8Sdjm 107e85b1b81Smiod static int 108e85b1b81Smiod pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 109f1535dc8Sdjm { 110f1535dc8Sdjm DSA_PKEY_CTX *dctx, *sctx; 111e85b1b81Smiod 112f1535dc8Sdjm if (!pkey_dsa_init(dst)) 113f1535dc8Sdjm return 0; 114f1535dc8Sdjm sctx = src->data; 115f1535dc8Sdjm dctx = dst->data; 116f1535dc8Sdjm dctx->nbits = sctx->nbits; 117f1535dc8Sdjm dctx->qbits = sctx->qbits; 118f1535dc8Sdjm dctx->pmd = sctx->pmd; 119f1535dc8Sdjm dctx->md = sctx->md; 120f1535dc8Sdjm return 1; 121f1535dc8Sdjm } 122f1535dc8Sdjm 123e85b1b81Smiod static void 124e85b1b81Smiod pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) 125f1535dc8Sdjm { 126f1535dc8Sdjm DSA_PKEY_CTX *dctx = ctx->data; 127e85b1b81Smiod 1286f3a6cb1Sbeck free(dctx); 129f1535dc8Sdjm } 130f1535dc8Sdjm 131e85b1b81Smiod static int 1324a91dbbdStb pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *out_siglen, 133f1535dc8Sdjm const unsigned char *tbs, size_t tbslen) 134f1535dc8Sdjm { 135f1535dc8Sdjm DSA *dsa = ctx->pkey->pkey.dsa; 1364a91dbbdStb DSA_PKEY_CTX *dctx = ctx->data; 1374a91dbbdStb unsigned int siglen; 138f1535dc8Sdjm 1394a91dbbdStb *out_siglen = 0; 140f1535dc8Sdjm 1414a91dbbdStb if (tbslen > INT_MAX) 1424a91dbbdStb return 0; 143f1535dc8Sdjm 1444a91dbbdStb if (dctx->md != NULL) { 1454a91dbbdStb if (tbslen != EVP_MD_size(dctx->md)) 1464a91dbbdStb return 0; 1474a91dbbdStb } 1484a91dbbdStb 1494a91dbbdStb if (!DSA_sign(0, tbs, tbslen, sig, &siglen, dsa)) 1504a91dbbdStb return 0; 1514a91dbbdStb 1524a91dbbdStb *out_siglen = siglen; 1534a91dbbdStb 154f1535dc8Sdjm return 1; 155f1535dc8Sdjm } 156f1535dc8Sdjm 157e85b1b81Smiod static int 158e85b1b81Smiod pkey_dsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, 159f1535dc8Sdjm const unsigned char *tbs, size_t tbslen) 160f1535dc8Sdjm { 161f1535dc8Sdjm DSA *dsa = ctx->pkey->pkey.dsa; 1624a91dbbdStb DSA_PKEY_CTX *dctx = ctx->data; 163f1535dc8Sdjm 1644a91dbbdStb if (tbslen > INT_MAX || siglen > INT_MAX) 1654a91dbbdStb return 0; 166f1535dc8Sdjm 1674a91dbbdStb if (dctx->md != NULL) { 1684a91dbbdStb if (tbslen != EVP_MD_size(dctx->md)) 1694a91dbbdStb return 0; 1704a91dbbdStb } 171f1535dc8Sdjm 1724a91dbbdStb return DSA_verify(0, tbs, tbslen, sig, siglen, dsa); 173f1535dc8Sdjm } 174f1535dc8Sdjm 175e85b1b81Smiod static int 176e85b1b81Smiod pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 177f1535dc8Sdjm { 178f1535dc8Sdjm DSA_PKEY_CTX *dctx = ctx->data; 179e85b1b81Smiod 180e85b1b81Smiod switch (type) { 181f1535dc8Sdjm case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: 182f1535dc8Sdjm if (p1 < 256) 183f1535dc8Sdjm return -2; 184f1535dc8Sdjm dctx->nbits = p1; 185f1535dc8Sdjm return 1; 186f1535dc8Sdjm 187f1535dc8Sdjm case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: 188f1535dc8Sdjm if (p1 != 160 && p1 != 224 && p1 && p1 != 256) 189f1535dc8Sdjm return -2; 190f1535dc8Sdjm dctx->qbits = p1; 191f1535dc8Sdjm return 1; 192f1535dc8Sdjm 193f1535dc8Sdjm case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: 1941da6504fSmiod switch (EVP_MD_type((const EVP_MD *)p2)) { 1951da6504fSmiod case NID_sha1: 1961da6504fSmiod case NID_sha224: 1971da6504fSmiod case NID_sha256: 1981da6504fSmiod break; 1991da6504fSmiod default: 2005067ae9fSbeck DSAerror(DSA_R_INVALID_DIGEST_TYPE); 201f1535dc8Sdjm return 0; 202f1535dc8Sdjm } 203f1535dc8Sdjm dctx->md = p2; 204f1535dc8Sdjm return 1; 205f1535dc8Sdjm 206f1535dc8Sdjm case EVP_PKEY_CTRL_MD: 2079a5a6ad9Stb /* ANSI X9.57 and NIST CSOR. */ 208*a5aac4c5Stb switch (EVP_MD_type(p2)) { 2091da6504fSmiod case NID_sha1: 2101da6504fSmiod case NID_dsa: 2111da6504fSmiod case NID_dsaWithSHA: 2121da6504fSmiod case NID_sha224: 2131da6504fSmiod case NID_sha256: 2141da6504fSmiod case NID_sha384: 2151da6504fSmiod case NID_sha512: 2169a5a6ad9Stb case NID_sha3_224: 2179a5a6ad9Stb case NID_sha3_256: 2189a5a6ad9Stb case NID_sha3_384: 2199a5a6ad9Stb case NID_sha3_512: 2201da6504fSmiod break; 2211da6504fSmiod default: 2225067ae9fSbeck DSAerror(DSA_R_INVALID_DIGEST_TYPE); 223f1535dc8Sdjm return 0; 224f1535dc8Sdjm } 225f1535dc8Sdjm dctx->md = p2; 226f1535dc8Sdjm return 1; 227f1535dc8Sdjm 2286627381bSjsing case EVP_PKEY_CTRL_GET_MD: 2296627381bSjsing *(const EVP_MD **)p2 = dctx->md; 2306627381bSjsing return 1; 2316627381bSjsing 232f1535dc8Sdjm case EVP_PKEY_CTRL_DIGESTINIT: 233f1535dc8Sdjm case EVP_PKEY_CTRL_PKCS7_SIGN: 234f1535dc8Sdjm case EVP_PKEY_CTRL_CMS_SIGN: 235f1535dc8Sdjm return 1; 236f1535dc8Sdjm 237f1535dc8Sdjm case EVP_PKEY_CTRL_PEER_KEY: 2385067ae9fSbeck DSAerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 239f1535dc8Sdjm return -2; 240f1535dc8Sdjm default: 241f1535dc8Sdjm return -2; 242f1535dc8Sdjm } 243f1535dc8Sdjm } 244f1535dc8Sdjm 245e85b1b81Smiod static int 246e85b1b81Smiod pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 247f1535dc8Sdjm { 2481e10d066Sop const char *errstr; 249b1d57841Sderaadt 250b1d57841Sderaadt if (!strcmp(type, "dsa_paramgen_bits")) { 251f1535dc8Sdjm int nbits; 252b1d57841Sderaadt 2531e10d066Sop nbits = strtonum(value, INT_MIN, INT_MAX, &errstr); 2541e10d066Sop if (errstr != NULL) 2551e10d066Sop return -2; 256f1535dc8Sdjm return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); 257e85b1b81Smiod } else if (!strcmp(type, "dsa_paramgen_q_bits")) { 258b1d57841Sderaadt int qbits; 259b1d57841Sderaadt 2601e10d066Sop qbits = strtonum(value, INT_MIN, INT_MAX, &errstr); 2611e10d066Sop if (errstr != NULL) 2621e10d066Sop return -2; 263e85b1b81Smiod return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, 264e85b1b81Smiod EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, 265e85b1b81Smiod qbits, NULL); 266e85b1b81Smiod } else if (!strcmp(type, "dsa_paramgen_md")) { 267e85b1b81Smiod return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, 268e85b1b81Smiod EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 269f1535dc8Sdjm (void *)EVP_get_digestbyname(value)); 270f1535dc8Sdjm } 2711e10d066Sop 272f1535dc8Sdjm return -2; 273f1535dc8Sdjm } 274f1535dc8Sdjm 275e85b1b81Smiod static int 276e85b1b81Smiod pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 277f1535dc8Sdjm { 27891192740Stb DSA *dsa; 279f1535dc8Sdjm DSA_PKEY_CTX *dctx = ctx->data; 28091192740Stb BN_GENCB *pcb = NULL; 28191192740Stb BN_GENCB cb = {0}; 28291192740Stb int ret = 0; 283e85b1b81Smiod 28491192740Stb if ((dsa = DSA_new()) == NULL) 28591192740Stb goto err; 28691192740Stb if (ctx->pkey_gencb != NULL) { 287f1535dc8Sdjm pcb = &cb; 288f1535dc8Sdjm evp_pkey_set_cb_translate(pcb, ctx); 28991192740Stb } 29091192740Stb if (!dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, 29191192740Stb NULL, 0, NULL, NULL, NULL, pcb)) 29291192740Stb goto err; 29391192740Stb if (!EVP_PKEY_assign_DSA(pkey, dsa)) 29491192740Stb goto err; 29591192740Stb dsa = NULL; 29691192740Stb 29791192740Stb ret = 1; 29891192740Stb 29991192740Stb err: 300f1535dc8Sdjm DSA_free(dsa); 30191192740Stb 302f1535dc8Sdjm return ret; 303f1535dc8Sdjm } 304f1535dc8Sdjm 305e85b1b81Smiod static int 306e85b1b81Smiod pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 307f1535dc8Sdjm { 308f1535dc8Sdjm DSA *dsa = NULL; 309a21e6844Stb int ret = 0; 310e85b1b81Smiod 311e85b1b81Smiod if (ctx->pkey == NULL) { 3125067ae9fSbeck DSAerror(DSA_R_NO_PARAMETERS_SET); 313a21e6844Stb goto err; 314f1535dc8Sdjm } 315a21e6844Stb if ((dsa = DSA_new()) == NULL) 316a21e6844Stb goto err; 317a21e6844Stb if (!EVP_PKEY_set1_DSA(pkey, dsa)) 318a21e6844Stb goto err; 319a21e6844Stb 320f1535dc8Sdjm if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 321a21e6844Stb goto err; 322a21e6844Stb if (!DSA_generate_key(dsa)) 323a21e6844Stb goto err; 324a21e6844Stb 325a21e6844Stb ret = 1; 326a21e6844Stb 327a21e6844Stb err: 328a21e6844Stb DSA_free(dsa); 329a21e6844Stb 330a21e6844Stb return ret; 331f1535dc8Sdjm } 332f1535dc8Sdjm 333e402ce74Smiod const EVP_PKEY_METHOD dsa_pkey_meth = { 334e402ce74Smiod .pkey_id = EVP_PKEY_DSA, 335e402ce74Smiod .flags = EVP_PKEY_FLAG_AUTOARGLEN, 336f1535dc8Sdjm 337e402ce74Smiod .init = pkey_dsa_init, 338e402ce74Smiod .copy = pkey_dsa_copy, 339e402ce74Smiod .cleanup = pkey_dsa_cleanup, 340f1535dc8Sdjm 341e402ce74Smiod .paramgen = pkey_dsa_paramgen, 342f1535dc8Sdjm 343e402ce74Smiod .keygen = pkey_dsa_keygen, 344f1535dc8Sdjm 345e402ce74Smiod .sign = pkey_dsa_sign, 346f1535dc8Sdjm 347e402ce74Smiod .verify = pkey_dsa_verify, 348f1535dc8Sdjm 349e402ce74Smiod .ctrl = pkey_dsa_ctrl, 350e402ce74Smiod .ctrl_str = pkey_dsa_ctrl_str 351f1535dc8Sdjm }; 352