16f9291ceSJung-uk Kim /* 2*e71b7053SJung-uk Kim * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. 31f13597dSJung-uk Kim * 4*e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5*e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6*e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7*e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 81f13597dSJung-uk Kim */ 91f13597dSJung-uk Kim 101f13597dSJung-uk Kim #include <stdio.h> 11*e71b7053SJung-uk Kim #include "internal/cryptlib.h" 121f13597dSJung-uk Kim #include <openssl/asn1t.h> 131f13597dSJung-uk Kim #include <openssl/x509.h> 141f13597dSJung-uk Kim #include <openssl/evp.h> 151f13597dSJung-uk Kim #include <openssl/bn.h> 16*e71b7053SJung-uk Kim #include "internal/evp_int.h" 171f13597dSJung-uk Kim #include "dsa_locl.h" 181f13597dSJung-uk Kim 191f13597dSJung-uk Kim /* DSA pkey context structure */ 201f13597dSJung-uk Kim 216f9291ceSJung-uk Kim typedef struct { 221f13597dSJung-uk Kim /* Parameter gen parameters */ 231f13597dSJung-uk Kim int nbits; /* size of p in bits (default: 1024) */ 241f13597dSJung-uk Kim int qbits; /* size of q in bits (default: 160) */ 251f13597dSJung-uk Kim const EVP_MD *pmd; /* MD for parameter generation */ 261f13597dSJung-uk Kim /* Keygen callback info */ 271f13597dSJung-uk Kim int gentmp[2]; 281f13597dSJung-uk Kim /* message digest */ 291f13597dSJung-uk Kim const EVP_MD *md; /* MD for the signature */ 301f13597dSJung-uk Kim } DSA_PKEY_CTX; 311f13597dSJung-uk Kim 321f13597dSJung-uk Kim static int pkey_dsa_init(EVP_PKEY_CTX *ctx) 331f13597dSJung-uk Kim { 34*e71b7053SJung-uk Kim DSA_PKEY_CTX *dctx = OPENSSL_malloc(sizeof(*dctx)); 35*e71b7053SJung-uk Kim 36*e71b7053SJung-uk Kim if (dctx == NULL) 371f13597dSJung-uk Kim return 0; 381f13597dSJung-uk Kim dctx->nbits = 1024; 391f13597dSJung-uk Kim dctx->qbits = 160; 401f13597dSJung-uk Kim dctx->pmd = NULL; 411f13597dSJung-uk Kim dctx->md = NULL; 421f13597dSJung-uk Kim 431f13597dSJung-uk Kim ctx->data = dctx; 441f13597dSJung-uk Kim ctx->keygen_info = dctx->gentmp; 451f13597dSJung-uk Kim ctx->keygen_info_count = 2; 461f13597dSJung-uk Kim 471f13597dSJung-uk Kim return 1; 481f13597dSJung-uk Kim } 491f13597dSJung-uk Kim 501f13597dSJung-uk Kim static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) 511f13597dSJung-uk Kim { 521f13597dSJung-uk Kim DSA_PKEY_CTX *dctx, *sctx; 53*e71b7053SJung-uk Kim 541f13597dSJung-uk Kim if (!pkey_dsa_init(dst)) 551f13597dSJung-uk Kim return 0; 561f13597dSJung-uk Kim sctx = src->data; 571f13597dSJung-uk Kim dctx = dst->data; 581f13597dSJung-uk Kim dctx->nbits = sctx->nbits; 591f13597dSJung-uk Kim dctx->qbits = sctx->qbits; 601f13597dSJung-uk Kim dctx->pmd = sctx->pmd; 611f13597dSJung-uk Kim dctx->md = sctx->md; 621f13597dSJung-uk Kim return 1; 631f13597dSJung-uk Kim } 641f13597dSJung-uk Kim 651f13597dSJung-uk Kim static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx) 661f13597dSJung-uk Kim { 671f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 681f13597dSJung-uk Kim OPENSSL_free(dctx); 691f13597dSJung-uk Kim } 701f13597dSJung-uk Kim 716f9291ceSJung-uk Kim static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, 726f9291ceSJung-uk Kim size_t *siglen, const unsigned char *tbs, 736f9291ceSJung-uk Kim size_t tbslen) 741f13597dSJung-uk Kim { 75*e71b7053SJung-uk Kim int ret; 761f13597dSJung-uk Kim unsigned int sltmp; 771f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 781f13597dSJung-uk Kim DSA *dsa = ctx->pkey->pkey.dsa; 791f13597dSJung-uk Kim 80*e71b7053SJung-uk Kim if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md)) 81*e71b7053SJung-uk Kim return 0; 821f13597dSJung-uk Kim 83*e71b7053SJung-uk Kim ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa); 841f13597dSJung-uk Kim 851f13597dSJung-uk Kim if (ret <= 0) 861f13597dSJung-uk Kim return ret; 871f13597dSJung-uk Kim *siglen = sltmp; 881f13597dSJung-uk Kim return 1; 891f13597dSJung-uk Kim } 901f13597dSJung-uk Kim 911f13597dSJung-uk Kim static int pkey_dsa_verify(EVP_PKEY_CTX *ctx, 921f13597dSJung-uk Kim const unsigned char *sig, size_t siglen, 931f13597dSJung-uk Kim const unsigned char *tbs, size_t tbslen) 941f13597dSJung-uk Kim { 95*e71b7053SJung-uk Kim int ret; 961f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 971f13597dSJung-uk Kim DSA *dsa = ctx->pkey->pkey.dsa; 981f13597dSJung-uk Kim 99*e71b7053SJung-uk Kim if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md)) 100*e71b7053SJung-uk Kim return 0; 1011f13597dSJung-uk Kim 102*e71b7053SJung-uk Kim ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa); 1031f13597dSJung-uk Kim 1041f13597dSJung-uk Kim return ret; 1051f13597dSJung-uk Kim } 1061f13597dSJung-uk Kim 1071f13597dSJung-uk Kim static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) 1081f13597dSJung-uk Kim { 1091f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 110*e71b7053SJung-uk Kim 1116f9291ceSJung-uk Kim switch (type) { 1121f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS: 1131f13597dSJung-uk Kim if (p1 < 256) 1141f13597dSJung-uk Kim return -2; 1151f13597dSJung-uk Kim dctx->nbits = p1; 1161f13597dSJung-uk Kim return 1; 1171f13597dSJung-uk Kim 1181f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS: 1191f13597dSJung-uk Kim if (p1 != 160 && p1 != 224 && p1 && p1 != 256) 1201f13597dSJung-uk Kim return -2; 1211f13597dSJung-uk Kim dctx->qbits = p1; 1221f13597dSJung-uk Kim return 1; 1231f13597dSJung-uk Kim 1241f13597dSJung-uk Kim case EVP_PKEY_CTRL_DSA_PARAMGEN_MD: 1251f13597dSJung-uk Kim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 1261f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 1276f9291ceSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha256) { 1281f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 1291f13597dSJung-uk Kim return 0; 1301f13597dSJung-uk Kim } 1316cf8931aSJung-uk Kim dctx->pmd = p2; 1321f13597dSJung-uk Kim return 1; 1331f13597dSJung-uk Kim 1341f13597dSJung-uk Kim case EVP_PKEY_CTRL_MD: 1351f13597dSJung-uk Kim if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 1361f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_dsa && 1371f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA && 1381f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 1391f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 1401f13597dSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 1416f9291ceSJung-uk Kim EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 1421f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE); 1431f13597dSJung-uk Kim return 0; 1441f13597dSJung-uk Kim } 1451f13597dSJung-uk Kim dctx->md = p2; 1461f13597dSJung-uk Kim return 1; 1471f13597dSJung-uk Kim 1487bded2dbSJung-uk Kim case EVP_PKEY_CTRL_GET_MD: 1497bded2dbSJung-uk Kim *(const EVP_MD **)p2 = dctx->md; 1507bded2dbSJung-uk Kim return 1; 1517bded2dbSJung-uk Kim 1521f13597dSJung-uk Kim case EVP_PKEY_CTRL_DIGESTINIT: 1531f13597dSJung-uk Kim case EVP_PKEY_CTRL_PKCS7_SIGN: 1541f13597dSJung-uk Kim case EVP_PKEY_CTRL_CMS_SIGN: 1551f13597dSJung-uk Kim return 1; 1561f13597dSJung-uk Kim 1571f13597dSJung-uk Kim case EVP_PKEY_CTRL_PEER_KEY: 1581f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL, 1591f13597dSJung-uk Kim EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 1601f13597dSJung-uk Kim return -2; 1611f13597dSJung-uk Kim default: 1621f13597dSJung-uk Kim return -2; 1631f13597dSJung-uk Kim 1641f13597dSJung-uk Kim } 1651f13597dSJung-uk Kim } 1661f13597dSJung-uk Kim 1671f13597dSJung-uk Kim static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, 1681f13597dSJung-uk Kim const char *type, const char *value) 1691f13597dSJung-uk Kim { 170*e71b7053SJung-uk Kim if (strcmp(type, "dsa_paramgen_bits") == 0) { 1711f13597dSJung-uk Kim int nbits; 1721f13597dSJung-uk Kim nbits = atoi(value); 1731f13597dSJung-uk Kim return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits); 1741f13597dSJung-uk Kim } 175*e71b7053SJung-uk Kim if (strcmp(type, "dsa_paramgen_q_bits") == 0) { 1761f13597dSJung-uk Kim int qbits = atoi(value); 1771f13597dSJung-uk Kim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 1786f9291ceSJung-uk Kim EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits, 1796f9291ceSJung-uk Kim NULL); 1801f13597dSJung-uk Kim } 181dea77ea6SJung-uk Kim if (strcmp(type, "dsa_paramgen_md") == 0) { 182dea77ea6SJung-uk Kim const EVP_MD *md = EVP_get_digestbyname(value); 183dea77ea6SJung-uk Kim 184dea77ea6SJung-uk Kim if (md == NULL) { 185dea77ea6SJung-uk Kim DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE); 186dea77ea6SJung-uk Kim return 0; 187dea77ea6SJung-uk Kim } 1881f13597dSJung-uk Kim return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, 1891f13597dSJung-uk Kim EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0, 190dea77ea6SJung-uk Kim (void *)md); 1911f13597dSJung-uk Kim } 1921f13597dSJung-uk Kim return -2; 1931f13597dSJung-uk Kim } 1941f13597dSJung-uk Kim 1951f13597dSJung-uk Kim static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 1961f13597dSJung-uk Kim { 1971f13597dSJung-uk Kim DSA *dsa = NULL; 1981f13597dSJung-uk Kim DSA_PKEY_CTX *dctx = ctx->data; 199*e71b7053SJung-uk Kim BN_GENCB *pcb; 2001f13597dSJung-uk Kim int ret; 201*e71b7053SJung-uk Kim 2026f9291ceSJung-uk Kim if (ctx->pkey_gencb) { 203*e71b7053SJung-uk Kim pcb = BN_GENCB_new(); 204*e71b7053SJung-uk Kim if (pcb == NULL) 205*e71b7053SJung-uk Kim return 0; 2061f13597dSJung-uk Kim evp_pkey_set_cb_translate(pcb, ctx); 2076f9291ceSJung-uk Kim } else 2081f13597dSJung-uk Kim pcb = NULL; 2091f13597dSJung-uk Kim dsa = DSA_new(); 210*e71b7053SJung-uk Kim if (dsa == NULL) { 211*e71b7053SJung-uk Kim BN_GENCB_free(pcb); 2121f13597dSJung-uk Kim return 0; 213*e71b7053SJung-uk Kim } 2141f13597dSJung-uk Kim ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd, 2151f13597dSJung-uk Kim NULL, 0, NULL, NULL, NULL, pcb); 216*e71b7053SJung-uk Kim BN_GENCB_free(pcb); 2171f13597dSJung-uk Kim if (ret) 2181f13597dSJung-uk Kim EVP_PKEY_assign_DSA(pkey, dsa); 2191f13597dSJung-uk Kim else 2201f13597dSJung-uk Kim DSA_free(dsa); 2211f13597dSJung-uk Kim return ret; 2221f13597dSJung-uk Kim } 2231f13597dSJung-uk Kim 2241f13597dSJung-uk Kim static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) 2251f13597dSJung-uk Kim { 2261f13597dSJung-uk Kim DSA *dsa = NULL; 227*e71b7053SJung-uk Kim 2286f9291ceSJung-uk Kim if (ctx->pkey == NULL) { 2291f13597dSJung-uk Kim DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET); 2301f13597dSJung-uk Kim return 0; 2311f13597dSJung-uk Kim } 2321f13597dSJung-uk Kim dsa = DSA_new(); 233*e71b7053SJung-uk Kim if (dsa == NULL) 2341f13597dSJung-uk Kim return 0; 2351f13597dSJung-uk Kim EVP_PKEY_assign_DSA(pkey, dsa); 2361f13597dSJung-uk Kim /* Note: if error return, pkey is freed by parent routine */ 2371f13597dSJung-uk Kim if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) 2381f13597dSJung-uk Kim return 0; 2391f13597dSJung-uk Kim return DSA_generate_key(pkey->pkey.dsa); 2401f13597dSJung-uk Kim } 2411f13597dSJung-uk Kim 2426f9291ceSJung-uk Kim const EVP_PKEY_METHOD dsa_pkey_meth = { 2431f13597dSJung-uk Kim EVP_PKEY_DSA, 2441f13597dSJung-uk Kim EVP_PKEY_FLAG_AUTOARGLEN, 2451f13597dSJung-uk Kim pkey_dsa_init, 2461f13597dSJung-uk Kim pkey_dsa_copy, 2471f13597dSJung-uk Kim pkey_dsa_cleanup, 2481f13597dSJung-uk Kim 2491f13597dSJung-uk Kim 0, 2501f13597dSJung-uk Kim pkey_dsa_paramgen, 2511f13597dSJung-uk Kim 2521f13597dSJung-uk Kim 0, 2531f13597dSJung-uk Kim pkey_dsa_keygen, 2541f13597dSJung-uk Kim 2551f13597dSJung-uk Kim 0, 2561f13597dSJung-uk Kim pkey_dsa_sign, 2571f13597dSJung-uk Kim 2581f13597dSJung-uk Kim 0, 2591f13597dSJung-uk Kim pkey_dsa_verify, 2601f13597dSJung-uk Kim 2611f13597dSJung-uk Kim 0, 0, 2621f13597dSJung-uk Kim 2631f13597dSJung-uk Kim 0, 0, 0, 0, 2641f13597dSJung-uk Kim 2651f13597dSJung-uk Kim 0, 0, 2661f13597dSJung-uk Kim 2671f13597dSJung-uk Kim 0, 0, 2681f13597dSJung-uk Kim 2691f13597dSJung-uk Kim 0, 0, 2701f13597dSJung-uk Kim 2711f13597dSJung-uk Kim pkey_dsa_ctrl, 2721f13597dSJung-uk Kim pkey_dsa_ctrl_str 2731f13597dSJung-uk Kim }; 274