16f9291ceSJung-uk Kim /* 26f9291ceSJung-uk Kim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 36f9291ceSJung-uk Kim * 2006. 41f13597dSJung-uk Kim */ 51f13597dSJung-uk Kim /* ==================================================================== 6*dea77ea6SJung-uk Kim * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved. 71f13597dSJung-uk Kim * 81f13597dSJung-uk Kim * Redistribution and use in source and binary forms, with or without 91f13597dSJung-uk Kim * modification, are permitted provided that the following conditions 101f13597dSJung-uk Kim * are met: 111f13597dSJung-uk Kim * 121f13597dSJung-uk Kim * 1. Redistributions of source code must retain the above copyright 131f13597dSJung-uk Kim * notice, this list of conditions and the following disclaimer. 141f13597dSJung-uk Kim * 151f13597dSJung-uk Kim * 2. Redistributions in binary form must reproduce the above copyright 161f13597dSJung-uk Kim * notice, this list of conditions and the following disclaimer in 171f13597dSJung-uk Kim * the documentation and/or other materials provided with the 181f13597dSJung-uk Kim * distribution. 191f13597dSJung-uk Kim * 201f13597dSJung-uk Kim * 3. All advertising materials mentioning features or use of this 211f13597dSJung-uk Kim * software must display the following acknowledgment: 221f13597dSJung-uk Kim * "This product includes software developed by the OpenSSL Project 231f13597dSJung-uk Kim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 241f13597dSJung-uk Kim * 251f13597dSJung-uk Kim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 261f13597dSJung-uk Kim * endorse or promote products derived from this software without 271f13597dSJung-uk Kim * prior written permission. For written permission, please contact 281f13597dSJung-uk Kim * licensing@OpenSSL.org. 291f13597dSJung-uk Kim * 301f13597dSJung-uk Kim * 5. Products derived from this software may not be called "OpenSSL" 311f13597dSJung-uk Kim * nor may "OpenSSL" appear in their names without prior written 321f13597dSJung-uk Kim * permission of the OpenSSL Project. 331f13597dSJung-uk Kim * 341f13597dSJung-uk Kim * 6. Redistributions of any form whatsoever must retain the following 351f13597dSJung-uk Kim * acknowledgment: 361f13597dSJung-uk Kim * "This product includes software developed by the OpenSSL Project 371f13597dSJung-uk Kim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 381f13597dSJung-uk Kim * 391f13597dSJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 401f13597dSJung-uk Kim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 411f13597dSJung-uk Kim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 421f13597dSJung-uk Kim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 431f13597dSJung-uk Kim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 441f13597dSJung-uk Kim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 451f13597dSJung-uk Kim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 461f13597dSJung-uk Kim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 471f13597dSJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 481f13597dSJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 491f13597dSJung-uk Kim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 501f13597dSJung-uk Kim * OF THE POSSIBILITY OF SUCH DAMAGE. 511f13597dSJung-uk Kim * ==================================================================== 521f13597dSJung-uk Kim * 531f13597dSJung-uk Kim * This product includes cryptographic software written by Eric Young 541f13597dSJung-uk Kim * (eay@cryptsoft.com). This product includes software written by Tim 551f13597dSJung-uk Kim * Hudson (tjh@cryptsoft.com). 561f13597dSJung-uk Kim * 571f13597dSJung-uk Kim */ 581f13597dSJung-uk Kim 591f13597dSJung-uk Kim #include <stdio.h> 601f13597dSJung-uk Kim #include "cryptlib.h" 611f13597dSJung-uk Kim #include <openssl/asn1t.h> 621f13597dSJung-uk Kim #include <openssl/x509.h> 631f13597dSJung-uk Kim #include <openssl/evp.h> 641f13597dSJung-uk Kim #include <openssl/bn.h> 651f13597dSJung-uk Kim #include "evp_locl.h" 661f13597dSJung-uk Kim #include "dsa_locl.h" 671f13597dSJung-uk Kim 681f13597dSJung-uk Kim /* DSA pkey context structure */ 691f13597dSJung-uk Kim 706f9291ceSJung-uk Kim typedef struct { 711f13597dSJung-uk Kim /* Parameter gen parameters */ 721f13597dSJung-uk Kim int nbits; /* size of p in bits (default: 1024) */ 731f13597dSJung-uk Kim int qbits; /* size of q in bits (default: 160) */ 741f13597dSJung-uk Kim const EVP_MD *pmd; /* MD for parameter generation */ 751f13597dSJung-uk Kim /* Keygen callback info */ 761f13597dSJung-uk Kim int gentmp[2]; 771f13597dSJung-uk Kim /* message digest */ 781f13597dSJung-uk Kim const EVP_MD *md; /* MD for the signature */ 791f13597dSJung-uk Kim } DSA_PKEY_CTX; 801f13597dSJung-uk Kim 811f13597dSJung-uk Kim static int pkey_dsa_init(EVP_PKEY_CTX *ctx) 821f13597dSJung-uk Kim { 831f13597dSJung-uk Kim DSA_PKEY_CTX *dctx; 841f13597dSJung-uk Kim dctx = OPENSSL_malloc(sizeof(DSA_PKEY_CTX)); 851f13597dSJung-uk Kim if (!dctx) 861f13597dSJung-uk Kim return 0; 871f13597dSJung-uk Kim dctx->nbits = 1024; 881f13597dSJung-uk Kim dctx->qbits = 160; 891f13597dSJung-uk Kim dctx->pmd = NULL; 901f13597dSJung-uk Kim dctx->md = NULL; 911f13597dSJung-uk Kim 921f13597dSJung-uk Kim ctx->data = dctx; 931f13597dSJung-uk Kim ctx->keygen_info = dctx->gentmp; 941f13597dSJung-uk Kim ctx->keygen_info_count = 2; 951f13597dSJung-uk Kim 961f13597dSJung-uk Kim return 1; 971f13597dSJung-uk Kim } 981f13597dSJung-uk Kim 991f13597dSJung-uk Kim static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 1001f13597dSJung-uk Kim { 1011f13597dSJung-uk Kim DSA_PKEY_CTX *dctx, *sctx; 1021f13597dSJung-uk Kim if (!pkey_dsa_init(dst)) 1031f13597dSJung-uk Kim return 0; 1041f13597dSJung-uk Kim sctx = src->data; 1051f13597dSJung-uk Kim dctx = dst->data; 1061f13597dSJung-uk Kim dctx->nbits = sctx->nbits; 1071f13597dSJung-uk Kim dctx->qbits = sctx->qbits; 1081f13597dSJung-uk Kim dctx->pmd = sctx->pmd; 1091f13597dSJung-uk Kim dctx->md = sctx->md; 1101f13597dSJung-uk Kim return 1; 1111f13597dSJung-uk Kim } 1121f13597dSJung-uk Kim 1131f13597dSJung-uk Kim static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) 1141f13597dSJung-uk Kim { 1151f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 1161f13597dSJung-uk Kim if (dctx) 1171f13597dSJung-uk Kim OPENSSL_free(dctx); 1181f13597dSJung-uk Kim } 1191f13597dSJung-uk Kim 1206f9291ceSJung-uk Kim static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, 1216f9291ceSJung-uk Kim size_t *siglen, const unsigned char *tbs, 1226f9291ceSJung-uk Kim size_t tbslen) 1231f13597dSJung-uk Kim { 1241f13597dSJung-uk Kim int ret, type; 1251f13597dSJung-uk Kim unsigned int sltmp; 1261f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 1271f13597dSJung-uk Kim DSA *dsa = ctx->pkey->pkey.dsa; 1281f13597dSJung-uk Kim 1291f13597dSJung-uk Kim if (dctx->md) 1301f13597dSJung-uk Kim type = EVP_MD_type(dctx->md); 1311f13597dSJung-uk Kim else 1321f13597dSJung-uk Kim type = NID_sha1; 1331f13597dSJung-uk Kim 1341f13597dSJung-uk Kim ret = DSA_sign(type, tbs, tbslen, sig, &sltmp, dsa); 1351f13597dSJung-uk Kim 1361f13597dSJung-uk Kim if (ret <= 0) 1371f13597dSJung-uk Kim return ret; 1381f13597dSJung-uk Kim *siglen = sltmp; 1391f13597dSJung-uk Kim return 1; 1401f13597dSJung-uk Kim } 1411f13597dSJung-uk Kim 1421f13597dSJung-uk Kim static int pkey_dsa_verify(EVP_PKEY_CTX *ctx, 1431f13597dSJung-uk Kim const unsigned char *sig, size_t siglen, 1441f13597dSJung-uk Kim const unsigned char *tbs, size_t tbslen) 1451f13597dSJung-uk Kim { 1461f13597dSJung-uk Kim int ret, type; 1471f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 1481f13597dSJung-uk Kim DSA *dsa = ctx->pkey->pkey.dsa; 1491f13597dSJung-uk Kim 1501f13597dSJung-uk Kim if (dctx->md) 1511f13597dSJung-uk Kim type = EVP_MD_type(dctx->md); 1521f13597dSJung-uk Kim else 1531f13597dSJung-uk Kim type = NID_sha1; 1541f13597dSJung-uk Kim 1551f13597dSJung-uk Kim ret = DSA_verify(type, tbs, tbslen, sig, siglen, dsa); 1561f13597dSJung-uk Kim 1571f13597dSJung-uk Kim return ret; 1581f13597dSJung-uk Kim } 1591f13597dSJung-uk Kim 1601f13597dSJung-uk Kim static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 1611f13597dSJung-uk Kim { 1621f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 1636f9291ceSJung-uk Kim switch (type) { 1641f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: 1651f13597dSJung-uk Kim if (p1 < 256) 1661f13597dSJung-uk Kim return -2; 1671f13597dSJung-uk Kim dctx->nbits = p1; 1681f13597dSJung-uk Kim return 1; 1691f13597dSJung-uk Kim 1701f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: 1711f13597dSJung-uk Kim if (p1 != 160 && p1 != 224 && p1 && p1 != 256) 1721f13597dSJung-uk Kim return -2; 1731f13597dSJung-uk Kim dctx->qbits = p1; 1741f13597dSJung-uk Kim return 1; 1751f13597dSJung-uk Kim 1761f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: 1771f13597dSJung-uk Kim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 1781f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 1796f9291ceSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha256) { 1801f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 1811f13597dSJung-uk Kim return 0; 1821f13597dSJung-uk Kim } 1836cf8931aSJung-uk Kim dctx->pmd = p2; 1841f13597dSJung-uk Kim return 1; 1851f13597dSJung-uk Kim 1861f13597dSJung-uk Kim case EVP_PKEY_CTRL_MD: 1871f13597dSJung-uk Kim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 1881f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_dsa && 1891f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA && 1901f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 1911f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 1921f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 1936f9291ceSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 1941f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 1951f13597dSJung-uk Kim return 0; 1961f13597dSJung-uk Kim } 1971f13597dSJung-uk Kim dctx->md = p2; 1981f13597dSJung-uk Kim return 1; 1991f13597dSJung-uk Kim 2007bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_MD: 2017bded2dbSJung-uk Kim *(const EVP_MD **)p2 = dctx->md; 2027bded2dbSJung-uk Kim return 1; 2037bded2dbSJung-uk Kim 2041f13597dSJung-uk Kim case EVP_PKEY_CTRL_DIGESTINIT: 2051f13597dSJung-uk Kim case EVP_PKEY_CTRL_PKCS7_SIGN: 2061f13597dSJung-uk Kim case EVP_PKEY_CTRL_CMS_SIGN: 2071f13597dSJung-uk Kim return 1; 2081f13597dSJung-uk Kim 2091f13597dSJung-uk Kim case EVP_PKEY_CTRL_PEER_KEY: 2101f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, 2111f13597dSJung-uk Kim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 2121f13597dSJung-uk Kim return -2; 2131f13597dSJung-uk Kim default: 2141f13597dSJung-uk Kim return -2; 2151f13597dSJung-uk Kim 2161f13597dSJung-uk Kim } 2171f13597dSJung-uk Kim } 2181f13597dSJung-uk Kim 2191f13597dSJung-uk Kim static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, 2201f13597dSJung-uk Kim const char *type, const char *value) 2211f13597dSJung-uk Kim { 2226f9291ceSJung-uk Kim if (!strcmp(type, "dsa_paramgen_bits")) { 2231f13597dSJung-uk Kim int nbits; 2241f13597dSJung-uk Kim nbits = atoi(value); 2251f13597dSJung-uk Kim return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); 2261f13597dSJung-uk Kim } 2276f9291ceSJung-uk Kim if (!strcmp(type, "dsa_paramgen_q_bits")) { 2281f13597dSJung-uk Kim int qbits = atoi(value); 2291f13597dSJung-uk Kim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 2306f9291ceSJung-uk Kim EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, 2316f9291ceSJung-uk Kim NULL); 2321f13597dSJung-uk Kim } 233*dea77ea6SJung-uk Kim if (strcmp(type, "dsa_paramgen_md") == 0) { 234*dea77ea6SJung-uk Kim const EVP_MD *md = EVP_get_digestbyname(value); 235*dea77ea6SJung-uk Kim 236*dea77ea6SJung-uk Kim if (md == NULL) { 237*dea77ea6SJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE); 238*dea77ea6SJung-uk Kim return 0; 239*dea77ea6SJung-uk Kim } 2401f13597dSJung-uk Kim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 2411f13597dSJung-uk Kim EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 242*dea77ea6SJung-uk Kim (void *)md); 2431f13597dSJung-uk Kim } 2441f13597dSJung-uk Kim return -2; 2451f13597dSJung-uk Kim } 2461f13597dSJung-uk Kim 2471f13597dSJung-uk Kim static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 2481f13597dSJung-uk Kim { 2491f13597dSJung-uk Kim DSA *dsa = NULL; 2501f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 2511f13597dSJung-uk Kim BN_GENCB *pcb, cb; 2521f13597dSJung-uk Kim int ret; 2536f9291ceSJung-uk Kim if (ctx->pkey_gencb) { 2541f13597dSJung-uk Kim pcb = &cb; 2551f13597dSJung-uk Kim evp_pkey_set_cb_translate(pcb, ctx); 2566f9291ceSJung-uk Kim } else 2571f13597dSJung-uk Kim pcb = NULL; 2581f13597dSJung-uk Kim dsa = DSA_new(); 2591f13597dSJung-uk Kim if (!dsa) 2601f13597dSJung-uk Kim return 0; 2611f13597dSJung-uk Kim ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, 2621f13597dSJung-uk Kim NULL, 0, NULL, NULL, NULL, pcb); 2631f13597dSJung-uk Kim if (ret) 2641f13597dSJung-uk Kim EVP_PKEY_assign_DSA(pkey, dsa); 2651f13597dSJung-uk Kim else 2661f13597dSJung-uk Kim DSA_free(dsa); 2671f13597dSJung-uk Kim return ret; 2681f13597dSJung-uk Kim } 2691f13597dSJung-uk Kim 2701f13597dSJung-uk Kim static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 2711f13597dSJung-uk Kim { 2721f13597dSJung-uk Kim DSA *dsa = NULL; 2736f9291ceSJung-uk Kim if (ctx->pkey == NULL) { 2741f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET); 2751f13597dSJung-uk Kim return 0; 2761f13597dSJung-uk Kim } 2771f13597dSJung-uk Kim dsa = DSA_new(); 2781f13597dSJung-uk Kim if (!dsa) 2791f13597dSJung-uk Kim return 0; 2801f13597dSJung-uk Kim EVP_PKEY_assign_DSA(pkey, dsa); 2811f13597dSJung-uk Kim /* Note: if error return, pkey is freed by parent routine */ 2821f13597dSJung-uk Kim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 2831f13597dSJung-uk Kim return 0; 2841f13597dSJung-uk Kim return DSA_generate_key(pkey->pkey.dsa); 2851f13597dSJung-uk Kim } 2861f13597dSJung-uk Kim 2876f9291ceSJung-uk Kim const EVP_PKEY_METHOD dsa_pkey_meth = { 2881f13597dSJung-uk Kim EVP_PKEY_DSA, 2891f13597dSJung-uk Kim EVP_PKEY_FLAG_AUTOARGLEN, 2901f13597dSJung-uk Kim pkey_dsa_init, 2911f13597dSJung-uk Kim pkey_dsa_copy, 2921f13597dSJung-uk Kim pkey_dsa_cleanup, 2931f13597dSJung-uk Kim 2941f13597dSJung-uk Kim 0, 2951f13597dSJung-uk Kim pkey_dsa_paramgen, 2961f13597dSJung-uk Kim 2971f13597dSJung-uk Kim 0, 2981f13597dSJung-uk Kim pkey_dsa_keygen, 2991f13597dSJung-uk Kim 3001f13597dSJung-uk Kim 0, 3011f13597dSJung-uk Kim pkey_dsa_sign, 3021f13597dSJung-uk Kim 3031f13597dSJung-uk Kim 0, 3041f13597dSJung-uk Kim pkey_dsa_verify, 3051f13597dSJung-uk Kim 3061f13597dSJung-uk Kim 0, 0, 3071f13597dSJung-uk Kim 3081f13597dSJung-uk Kim 0, 0, 0, 0, 3091f13597dSJung-uk Kim 3101f13597dSJung-uk Kim 0, 0, 3111f13597dSJung-uk Kim 3121f13597dSJung-uk Kim 0, 0, 3131f13597dSJung-uk Kim 3141f13597dSJung-uk Kim 0, 0, 3151f13597dSJung-uk Kim 3161f13597dSJung-uk Kim pkey_dsa_ctrl, 3171f13597dSJung-uk Kim pkey_dsa_ctrl_str 3181f13597dSJung-uk Kim }; 319