1*cca6fc52SDaniel Fojt /* $OpenBSD: dsa_pmeth.c,v 1.12 2019/09/09 18:06:25 jsing Exp $ */ 2f5b1c8a1SJohn Marino /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3f5b1c8a1SJohn Marino * project 2006. 4f5b1c8a1SJohn Marino */ 5f5b1c8a1SJohn Marino /* ==================================================================== 6f5b1c8a1SJohn Marino * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7f5b1c8a1SJohn Marino * 8f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without 9f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions 10f5b1c8a1SJohn Marino * are met: 11f5b1c8a1SJohn Marino * 12f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright 13f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer. 14f5b1c8a1SJohn Marino * 15f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright 16f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in 17f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the 18f5b1c8a1SJohn Marino * distribution. 19f5b1c8a1SJohn Marino * 20f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this 21f5b1c8a1SJohn Marino * software must display the following acknowledgment: 22f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 23f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24f5b1c8a1SJohn Marino * 25f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26f5b1c8a1SJohn Marino * endorse or promote products derived from this software without 27f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact 28f5b1c8a1SJohn Marino * licensing@OpenSSL.org. 29f5b1c8a1SJohn Marino * 30f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL" 31f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written 32f5b1c8a1SJohn Marino * permission of the OpenSSL Project. 33f5b1c8a1SJohn Marino * 34f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following 35f5b1c8a1SJohn Marino * acknowledgment: 36f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project 37f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38f5b1c8a1SJohn Marino * 39f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE. 51f5b1c8a1SJohn Marino * ==================================================================== 52f5b1c8a1SJohn Marino * 53f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young 54f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim 55f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com). 56f5b1c8a1SJohn Marino * 57f5b1c8a1SJohn Marino */ 58f5b1c8a1SJohn Marino 59f5b1c8a1SJohn Marino #include <limits.h> 60f5b1c8a1SJohn Marino #include <stdio.h> 61f5b1c8a1SJohn Marino #include <string.h> 62f5b1c8a1SJohn Marino 63f5b1c8a1SJohn Marino #include <openssl/asn1t.h> 64f5b1c8a1SJohn Marino #include <openssl/bn.h> 65f5b1c8a1SJohn Marino #include <openssl/err.h> 66f5b1c8a1SJohn Marino #include <openssl/evp.h> 67f5b1c8a1SJohn Marino #include <openssl/x509.h> 68f5b1c8a1SJohn Marino 69f5b1c8a1SJohn Marino #include "dsa_locl.h" 70f5b1c8a1SJohn Marino #include "evp_locl.h" 71f5b1c8a1SJohn Marino 72f5b1c8a1SJohn Marino /* DSA pkey context structure */ 73f5b1c8a1SJohn Marino 74f5b1c8a1SJohn Marino typedef struct { 75f5b1c8a1SJohn Marino /* Parameter gen parameters */ 76f5b1c8a1SJohn Marino int nbits; /* size of p in bits (default: 1024) */ 77f5b1c8a1SJohn Marino int qbits; /* size of q in bits (default: 160) */ 78f5b1c8a1SJohn Marino const EVP_MD *pmd; /* MD for parameter generation */ 79f5b1c8a1SJohn Marino /* Keygen callback info */ 80f5b1c8a1SJohn Marino int gentmp[2]; 81f5b1c8a1SJohn Marino /* message digest */ 82f5b1c8a1SJohn Marino const EVP_MD *md; /* MD for the signature */ 83f5b1c8a1SJohn Marino } DSA_PKEY_CTX; 84f5b1c8a1SJohn Marino 85f5b1c8a1SJohn Marino static int 86f5b1c8a1SJohn Marino pkey_dsa_init(EVP_PKEY_CTX *ctx) 87f5b1c8a1SJohn Marino { 88f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx; 89f5b1c8a1SJohn Marino 90f5b1c8a1SJohn Marino dctx = malloc(sizeof(DSA_PKEY_CTX)); 91f5b1c8a1SJohn Marino if (!dctx) 92f5b1c8a1SJohn Marino return 0; 93f5b1c8a1SJohn Marino dctx->nbits = 1024; 94f5b1c8a1SJohn Marino dctx->qbits = 160; 95f5b1c8a1SJohn Marino dctx->pmd = NULL; 96f5b1c8a1SJohn Marino dctx->md = NULL; 97f5b1c8a1SJohn Marino 98f5b1c8a1SJohn Marino ctx->data = dctx; 99f5b1c8a1SJohn Marino ctx->keygen_info = dctx->gentmp; 100f5b1c8a1SJohn Marino ctx->keygen_info_count = 2; 101f5b1c8a1SJohn Marino 102f5b1c8a1SJohn Marino return 1; 103f5b1c8a1SJohn Marino } 104f5b1c8a1SJohn Marino 105f5b1c8a1SJohn Marino static int 106f5b1c8a1SJohn Marino pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 107f5b1c8a1SJohn Marino { 108f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx, *sctx; 109f5b1c8a1SJohn Marino 110f5b1c8a1SJohn Marino if (!pkey_dsa_init(dst)) 111f5b1c8a1SJohn Marino return 0; 112f5b1c8a1SJohn Marino sctx = src->data; 113f5b1c8a1SJohn Marino dctx = dst->data; 114f5b1c8a1SJohn Marino dctx->nbits = sctx->nbits; 115f5b1c8a1SJohn Marino dctx->qbits = sctx->qbits; 116f5b1c8a1SJohn Marino dctx->pmd = sctx->pmd; 117f5b1c8a1SJohn Marino dctx->md = sctx->md; 118f5b1c8a1SJohn Marino return 1; 119f5b1c8a1SJohn Marino } 120f5b1c8a1SJohn Marino 121f5b1c8a1SJohn Marino static void 122f5b1c8a1SJohn Marino pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) 123f5b1c8a1SJohn Marino { 124f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx = ctx->data; 125f5b1c8a1SJohn Marino 126f5b1c8a1SJohn Marino free(dctx); 127f5b1c8a1SJohn Marino } 128f5b1c8a1SJohn Marino 129f5b1c8a1SJohn Marino static int 130f5b1c8a1SJohn Marino pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, 131f5b1c8a1SJohn Marino const unsigned char *tbs, size_t tbslen) 132f5b1c8a1SJohn Marino { 133f5b1c8a1SJohn Marino int ret, type; 134f5b1c8a1SJohn Marino unsigned int sltmp; 135f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx = ctx->data; 136f5b1c8a1SJohn Marino DSA *dsa = ctx->pkey->pkey.dsa; 137f5b1c8a1SJohn Marino 138f5b1c8a1SJohn Marino if (dctx->md) 139f5b1c8a1SJohn Marino type = EVP_MD_type(dctx->md); 140f5b1c8a1SJohn Marino else 141f5b1c8a1SJohn Marino type = NID_sha1; 142f5b1c8a1SJohn Marino 143f5b1c8a1SJohn Marino ret = DSA_sign(type, tbs, tbslen, sig, &sltmp, dsa); 144f5b1c8a1SJohn Marino 145f5b1c8a1SJohn Marino if (ret <= 0) 146f5b1c8a1SJohn Marino return ret; 147f5b1c8a1SJohn Marino *siglen = sltmp; 148f5b1c8a1SJohn Marino return 1; 149f5b1c8a1SJohn Marino } 150f5b1c8a1SJohn Marino 151f5b1c8a1SJohn Marino static int 152f5b1c8a1SJohn Marino pkey_dsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, 153f5b1c8a1SJohn Marino const unsigned char *tbs, size_t tbslen) 154f5b1c8a1SJohn Marino { 155f5b1c8a1SJohn Marino int ret, type; 156f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx = ctx->data; 157f5b1c8a1SJohn Marino DSA *dsa = ctx->pkey->pkey.dsa; 158f5b1c8a1SJohn Marino 159f5b1c8a1SJohn Marino if (dctx->md) 160f5b1c8a1SJohn Marino type = EVP_MD_type(dctx->md); 161f5b1c8a1SJohn Marino else 162f5b1c8a1SJohn Marino type = NID_sha1; 163f5b1c8a1SJohn Marino 164f5b1c8a1SJohn Marino ret = DSA_verify(type, tbs, tbslen, sig, siglen, dsa); 165f5b1c8a1SJohn Marino 166f5b1c8a1SJohn Marino return ret; 167f5b1c8a1SJohn Marino } 168f5b1c8a1SJohn Marino 169f5b1c8a1SJohn Marino static int 170f5b1c8a1SJohn Marino pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 171f5b1c8a1SJohn Marino { 172f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx = ctx->data; 173f5b1c8a1SJohn Marino 174f5b1c8a1SJohn Marino switch (type) { 175f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: 176f5b1c8a1SJohn Marino if (p1 < 256) 177f5b1c8a1SJohn Marino return -2; 178f5b1c8a1SJohn Marino dctx->nbits = p1; 179f5b1c8a1SJohn Marino return 1; 180f5b1c8a1SJohn Marino 181f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: 182f5b1c8a1SJohn Marino if (p1 != 160 && p1 != 224 && p1 && p1 != 256) 183f5b1c8a1SJohn Marino return -2; 184f5b1c8a1SJohn Marino dctx->qbits = p1; 185f5b1c8a1SJohn Marino return 1; 186f5b1c8a1SJohn Marino 187f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: 188f5b1c8a1SJohn Marino switch (EVP_MD_type((const EVP_MD *)p2)) { 189f5b1c8a1SJohn Marino case NID_sha1: 190f5b1c8a1SJohn Marino case NID_sha224: 191f5b1c8a1SJohn Marino case NID_sha256: 192f5b1c8a1SJohn Marino break; 193f5b1c8a1SJohn Marino default: 19472c33676SMaxim Ag DSAerror(DSA_R_INVALID_DIGEST_TYPE); 195f5b1c8a1SJohn Marino return 0; 196f5b1c8a1SJohn Marino } 197f5b1c8a1SJohn Marino dctx->md = p2; 198f5b1c8a1SJohn Marino return 1; 199f5b1c8a1SJohn Marino 200f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_MD: 201f5b1c8a1SJohn Marino switch (EVP_MD_type((const EVP_MD *)p2)) { 202f5b1c8a1SJohn Marino case NID_sha1: 203f5b1c8a1SJohn Marino case NID_dsa: 204f5b1c8a1SJohn Marino case NID_dsaWithSHA: 205f5b1c8a1SJohn Marino case NID_sha224: 206f5b1c8a1SJohn Marino case NID_sha256: 207f5b1c8a1SJohn Marino case NID_sha384: 208f5b1c8a1SJohn Marino case NID_sha512: 209f5b1c8a1SJohn Marino break; 210f5b1c8a1SJohn Marino default: 21172c33676SMaxim Ag DSAerror(DSA_R_INVALID_DIGEST_TYPE); 212f5b1c8a1SJohn Marino return 0; 213f5b1c8a1SJohn Marino } 214f5b1c8a1SJohn Marino dctx->md = p2; 215f5b1c8a1SJohn Marino return 1; 216f5b1c8a1SJohn Marino 217*cca6fc52SDaniel Fojt case EVP_PKEY_CTRL_GET_MD: 218*cca6fc52SDaniel Fojt *(const EVP_MD **)p2 = dctx->md; 219*cca6fc52SDaniel Fojt return 1; 220*cca6fc52SDaniel Fojt 221f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_DIGESTINIT: 222f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_PKCS7_SIGN: 223f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_CMS_SIGN: 224f5b1c8a1SJohn Marino return 1; 225f5b1c8a1SJohn Marino 226f5b1c8a1SJohn Marino case EVP_PKEY_CTRL_PEER_KEY: 22772c33676SMaxim Ag DSAerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 228f5b1c8a1SJohn Marino return -2; 229f5b1c8a1SJohn Marino default: 230f5b1c8a1SJohn Marino return -2; 231f5b1c8a1SJohn Marino } 232f5b1c8a1SJohn Marino } 233f5b1c8a1SJohn Marino 234f5b1c8a1SJohn Marino static int 235f5b1c8a1SJohn Marino pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) 236f5b1c8a1SJohn Marino { 237f5b1c8a1SJohn Marino long lval; 238f5b1c8a1SJohn Marino char *ep; 239f5b1c8a1SJohn Marino 240f5b1c8a1SJohn Marino if (!strcmp(type, "dsa_paramgen_bits")) { 241f5b1c8a1SJohn Marino int nbits; 242f5b1c8a1SJohn Marino 243f5b1c8a1SJohn Marino errno = 0; 244f5b1c8a1SJohn Marino lval = strtol(value, &ep, 10); 245f5b1c8a1SJohn Marino if (value[0] == '\0' || *ep != '\0') 246f5b1c8a1SJohn Marino goto not_a_number; 247f5b1c8a1SJohn Marino if ((errno == ERANGE && 248f5b1c8a1SJohn Marino (lval == LONG_MAX || lval == LONG_MIN)) || 249f5b1c8a1SJohn Marino (lval > INT_MAX || lval < INT_MIN)) 250f5b1c8a1SJohn Marino goto out_of_range; 251f5b1c8a1SJohn Marino nbits = lval; 252f5b1c8a1SJohn Marino return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); 253f5b1c8a1SJohn Marino } else if (!strcmp(type, "dsa_paramgen_q_bits")) { 254f5b1c8a1SJohn Marino int qbits; 255f5b1c8a1SJohn Marino 256f5b1c8a1SJohn Marino errno = 0; 257f5b1c8a1SJohn Marino lval = strtol(value, &ep, 10); 258f5b1c8a1SJohn Marino if (value[0] == '\0' || *ep != '\0') 259f5b1c8a1SJohn Marino goto not_a_number; 260f5b1c8a1SJohn Marino if ((errno == ERANGE && 261f5b1c8a1SJohn Marino (lval == LONG_MAX || lval == LONG_MIN)) || 262f5b1c8a1SJohn Marino (lval > INT_MAX || lval < INT_MIN)) 263f5b1c8a1SJohn Marino goto out_of_range; 264f5b1c8a1SJohn Marino qbits = lval; 265f5b1c8a1SJohn Marino return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, 266f5b1c8a1SJohn Marino EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, 267f5b1c8a1SJohn Marino qbits, NULL); 268f5b1c8a1SJohn Marino } else if (!strcmp(type, "dsa_paramgen_md")) { 269f5b1c8a1SJohn Marino return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, 270f5b1c8a1SJohn Marino EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 271f5b1c8a1SJohn Marino (void *)EVP_get_digestbyname(value)); 272f5b1c8a1SJohn Marino } 273f5b1c8a1SJohn Marino not_a_number: 274f5b1c8a1SJohn Marino out_of_range: 275f5b1c8a1SJohn Marino return -2; 276f5b1c8a1SJohn Marino } 277f5b1c8a1SJohn Marino 278f5b1c8a1SJohn Marino static int 279f5b1c8a1SJohn Marino pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 280f5b1c8a1SJohn Marino { 281f5b1c8a1SJohn Marino DSA *dsa = NULL; 282f5b1c8a1SJohn Marino DSA_PKEY_CTX *dctx = ctx->data; 283f5b1c8a1SJohn Marino BN_GENCB *pcb, cb; 284f5b1c8a1SJohn Marino int ret; 285f5b1c8a1SJohn Marino 286f5b1c8a1SJohn Marino if (ctx->pkey_gencb) { 287f5b1c8a1SJohn Marino pcb = &cb; 288f5b1c8a1SJohn Marino evp_pkey_set_cb_translate(pcb, ctx); 289f5b1c8a1SJohn Marino } else 290f5b1c8a1SJohn Marino pcb = NULL; 291f5b1c8a1SJohn Marino dsa = DSA_new(); 292f5b1c8a1SJohn Marino if (!dsa) 293f5b1c8a1SJohn Marino return 0; 294f5b1c8a1SJohn Marino ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, 295f5b1c8a1SJohn Marino NULL, 0, NULL, NULL, NULL, pcb); 296f5b1c8a1SJohn Marino if (ret) 297f5b1c8a1SJohn Marino EVP_PKEY_assign_DSA(pkey, dsa); 298f5b1c8a1SJohn Marino else 299f5b1c8a1SJohn Marino DSA_free(dsa); 300f5b1c8a1SJohn Marino return ret; 301f5b1c8a1SJohn Marino } 302f5b1c8a1SJohn Marino 303f5b1c8a1SJohn Marino static int 304f5b1c8a1SJohn Marino pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 305f5b1c8a1SJohn Marino { 306f5b1c8a1SJohn Marino DSA *dsa = NULL; 307f5b1c8a1SJohn Marino 308f5b1c8a1SJohn Marino if (ctx->pkey == NULL) { 30972c33676SMaxim Ag DSAerror(DSA_R_NO_PARAMETERS_SET); 310f5b1c8a1SJohn Marino return 0; 311f5b1c8a1SJohn Marino } 312f5b1c8a1SJohn Marino dsa = DSA_new(); 313f5b1c8a1SJohn Marino if (!dsa) 314f5b1c8a1SJohn Marino return 0; 315f5b1c8a1SJohn Marino EVP_PKEY_assign_DSA(pkey, dsa); 316f5b1c8a1SJohn Marino /* Note: if error return, pkey is freed by parent routine */ 317f5b1c8a1SJohn Marino if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 318f5b1c8a1SJohn Marino return 0; 319f5b1c8a1SJohn Marino return DSA_generate_key(pkey->pkey.dsa); 320f5b1c8a1SJohn Marino } 321f5b1c8a1SJohn Marino 322f5b1c8a1SJohn Marino const EVP_PKEY_METHOD dsa_pkey_meth = { 323f5b1c8a1SJohn Marino .pkey_id = EVP_PKEY_DSA, 324f5b1c8a1SJohn Marino .flags = EVP_PKEY_FLAG_AUTOARGLEN, 325f5b1c8a1SJohn Marino 326f5b1c8a1SJohn Marino .init = pkey_dsa_init, 327f5b1c8a1SJohn Marino .copy = pkey_dsa_copy, 328f5b1c8a1SJohn Marino .cleanup = pkey_dsa_cleanup, 329f5b1c8a1SJohn Marino 330f5b1c8a1SJohn Marino .paramgen = pkey_dsa_paramgen, 331f5b1c8a1SJohn Marino 332f5b1c8a1SJohn Marino .keygen = pkey_dsa_keygen, 333f5b1c8a1SJohn Marino 334f5b1c8a1SJohn Marino .sign = pkey_dsa_sign, 335f5b1c8a1SJohn Marino 336f5b1c8a1SJohn Marino .verify = pkey_dsa_verify, 337f5b1c8a1SJohn Marino 338f5b1c8a1SJohn Marino .ctrl = pkey_dsa_ctrl, 339f5b1c8a1SJohn Marino .ctrl_str = pkey_dsa_ctrl_str 340f5b1c8a1SJohn Marino }; 341