Blame crypto/dsa/dsa_pmeth.c

Packit c4476c
/*
Packit c4476c
 * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Packit c4476c
 *
Packit c4476c
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit c4476c
 * this file except in compliance with the License.  You can obtain a copy
Packit c4476c
 * in the file LICENSE in the source distribution or at
Packit c4476c
 * https://www.openssl.org/source/license.html
Packit c4476c
 */
Packit c4476c
Packit c4476c
#include <stdio.h>
Packit c4476c
#include "internal/cryptlib.h"
Packit c4476c
#include <openssl/asn1t.h>
Packit c4476c
#include <openssl/x509.h>
Packit c4476c
#include <openssl/evp.h>
Packit c4476c
#include <openssl/bn.h>
Packit c4476c
#include "crypto/evp.h"
Packit c4476c
#include "dsa_local.h"
Packit c4476c
Packit c4476c
/* DSA pkey context structure */
Packit c4476c
Packit c4476c
typedef struct {
Packit c4476c
    /* Parameter gen parameters */
Packit c4476c
    int nbits;                  /* size of p in bits (default: 2048) */
Packit c4476c
    int qbits;                  /* size of q in bits (default: 224) */
Packit c4476c
    const EVP_MD *pmd;          /* MD for parameter generation */
Packit c4476c
    /* Keygen callback info */
Packit c4476c
    int gentmp[2];
Packit c4476c
    /* message digest */
Packit c4476c
    const EVP_MD *md;           /* MD for the signature */
Packit c4476c
} DSA_PKEY_CTX;
Packit c4476c
Packit c4476c
static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
Packit c4476c
{
Packit c4476c
    DSA_PKEY_CTX *dctx = OPENSSL_malloc(sizeof(*dctx));
Packit c4476c
Packit c4476c
    if (dctx == NULL)
Packit c4476c
        return 0;
Packit c4476c
    dctx->nbits = 2048;
Packit c4476c
    dctx->qbits = 224;
Packit c4476c
    dctx->pmd = NULL;
Packit c4476c
    dctx->md = NULL;
Packit c4476c
Packit c4476c
    ctx->data = dctx;
Packit c4476c
    ctx->keygen_info = dctx->gentmp;
Packit c4476c
    ctx->keygen_info_count = 2;
Packit c4476c
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
Packit c4476c
{
Packit c4476c
    DSA_PKEY_CTX *dctx, *sctx;
Packit c4476c
Packit c4476c
    if (!pkey_dsa_init(dst))
Packit c4476c
        return 0;
Packit c4476c
    sctx = src->data;
Packit c4476c
    dctx = dst->data;
Packit c4476c
    dctx->nbits = sctx->nbits;
Packit c4476c
    dctx->qbits = sctx->qbits;
Packit c4476c
    dctx->pmd = sctx->pmd;
Packit c4476c
    dctx->md = sctx->md;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
Packit c4476c
{
Packit c4476c
    DSA_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    OPENSSL_free(dctx);
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
Packit c4476c
                         size_t *siglen, const unsigned char *tbs,
Packit c4476c
                         size_t tbslen)
Packit c4476c
{
Packit c4476c
    int ret;
Packit c4476c
    unsigned int sltmp;
Packit c4476c
    DSA_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    DSA *dsa = ctx->pkey->pkey.dsa;
Packit c4476c
Packit c4476c
    if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa);
Packit c4476c
Packit c4476c
    if (ret <= 0)
Packit c4476c
        return ret;
Packit c4476c
    *siglen = sltmp;
Packit c4476c
    return 1;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_verify(EVP_PKEY_CTX *ctx,
Packit c4476c
                           const unsigned char *sig, size_t siglen,
Packit c4476c
                           const unsigned char *tbs, size_t tbslen)
Packit c4476c
{
Packit c4476c
    int ret;
Packit c4476c
    DSA_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    DSA *dsa = ctx->pkey->pkey.dsa;
Packit c4476c
Packit c4476c
    if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
Packit c4476c
        return 0;
Packit c4476c
Packit c4476c
    ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa);
Packit c4476c
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
Packit c4476c
{
Packit c4476c
    DSA_PKEY_CTX *dctx = ctx->data;
Packit c4476c
Packit c4476c
    switch (type) {
Packit c4476c
    case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
Packit c4476c
        if (p1 < 256)
Packit c4476c
            return -2;
Packit c4476c
        dctx->nbits = p1;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
Packit c4476c
        if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
Packit c4476c
            return -2;
Packit c4476c
        dctx->qbits = p1;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
Packit c4476c
        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha256) {
Packit c4476c
            DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        dctx->pmd = p2;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_MD:
Packit c4476c
        if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_dsa &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
Packit c4476c
            EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
Packit c4476c
            DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        dctx->md = p2;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_GET_MD:
Packit c4476c
        *(const EVP_MD **)p2 = dctx->md;
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_DIGESTINIT:
Packit c4476c
    case EVP_PKEY_CTRL_PKCS7_SIGN:
Packit c4476c
    case EVP_PKEY_CTRL_CMS_SIGN:
Packit c4476c
        return 1;
Packit c4476c
Packit c4476c
    case EVP_PKEY_CTRL_PEER_KEY:
Packit c4476c
        DSAerr(DSA_F_PKEY_DSA_CTRL,
Packit c4476c
               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
Packit c4476c
        return -2;
Packit c4476c
    default:
Packit c4476c
        return -2;
Packit c4476c
Packit c4476c
    }
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
Packit c4476c
                             const char *type, const char *value)
Packit c4476c
{
Packit c4476c
    if (strcmp(type, "dsa_paramgen_bits") == 0) {
Packit c4476c
        int nbits;
Packit c4476c
        nbits = atoi(value);
Packit c4476c
        return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
Packit c4476c
    }
Packit c4476c
    if (strcmp(type, "dsa_paramgen_q_bits") == 0) {
Packit c4476c
        int qbits = atoi(value);
Packit c4476c
        return EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits);
Packit c4476c
    }
Packit c4476c
    if (strcmp(type, "dsa_paramgen_md") == 0) {
Packit c4476c
        const EVP_MD *md = EVP_get_digestbyname(value);
Packit c4476c
Packit c4476c
        if (md == NULL) {
Packit c4476c
            DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE);
Packit c4476c
            return 0;
Packit c4476c
        }
Packit c4476c
        return EVP_PKEY_CTX_set_dsa_paramgen_md(ctx, md);
Packit c4476c
    }
Packit c4476c
    return -2;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
Packit c4476c
{
Packit c4476c
    DSA *dsa = NULL;
Packit c4476c
    DSA_PKEY_CTX *dctx = ctx->data;
Packit c4476c
    BN_GENCB *pcb;
Packit c4476c
    int ret;
Packit c4476c
Packit c4476c
    if (ctx->pkey_gencb) {
Packit c4476c
        pcb = BN_GENCB_new();
Packit c4476c
        if (pcb == NULL)
Packit c4476c
            return 0;
Packit c4476c
        evp_pkey_set_cb_translate(pcb, ctx);
Packit c4476c
    } else
Packit c4476c
        pcb = NULL;
Packit c4476c
    dsa = DSA_new();
Packit c4476c
    if (dsa == NULL) {
Packit c4476c
        BN_GENCB_free(pcb);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    ret = dsa_builtin_paramgen2(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
Packit c4476c
                               NULL, 0, -1, NULL, NULL, NULL, pcb);
Packit c4476c
    BN_GENCB_free(pcb);
Packit c4476c
    if (ret)
Packit c4476c
        EVP_PKEY_assign_DSA(pkey, dsa);
Packit c4476c
    else
Packit c4476c
        DSA_free(dsa);
Packit c4476c
    return ret;
Packit c4476c
}
Packit c4476c
Packit c4476c
static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
Packit c4476c
{
Packit c4476c
    DSA *dsa = NULL;
Packit c4476c
Packit c4476c
    if (ctx->pkey == NULL) {
Packit c4476c
        DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET);
Packit c4476c
        return 0;
Packit c4476c
    }
Packit c4476c
    dsa = DSA_new();
Packit c4476c
    if (dsa == NULL)
Packit c4476c
        return 0;
Packit c4476c
    EVP_PKEY_assign_DSA(pkey, dsa);
Packit c4476c
    /* Note: if error return, pkey is freed by parent routine */
Packit c4476c
    if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
Packit c4476c
        return 0;
Packit c4476c
    return DSA_generate_key(pkey->pkey.dsa);
Packit c4476c
}
Packit c4476c
Packit c4476c
const EVP_PKEY_METHOD dsa_pkey_meth = {
Packit c4476c
    EVP_PKEY_DSA,
Packit c4476c
    EVP_PKEY_FLAG_AUTOARGLEN | EVP_PKEY_FLAG_FIPS,
Packit c4476c
    pkey_dsa_init,
Packit c4476c
    pkey_dsa_copy,
Packit c4476c
    pkey_dsa_cleanup,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_dsa_paramgen,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_dsa_keygen,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_dsa_sign,
Packit c4476c
Packit c4476c
    0,
Packit c4476c
    pkey_dsa_verify,
Packit c4476c
Packit c4476c
    0, 0,
Packit c4476c
Packit c4476c
    0, 0, 0, 0,
Packit c4476c
Packit c4476c
    0, 0,
Packit c4476c
Packit c4476c
    0, 0,
Packit c4476c
Packit c4476c
    0, 0,
Packit c4476c
Packit c4476c
    pkey_dsa_ctrl,
Packit c4476c
    pkey_dsa_ctrl_str
Packit c4476c
};
Packit c4476c
Packit c4476c
const EVP_PKEY_METHOD *dsa_pkey_method(void)
Packit c4476c
{
Packit c4476c
    return &dsa_pkey_meth;
Packit c4476c
}