Blame crypto/poly1305/poly1305_pmeth.c

Packit Service 084de1
/*
Packit Service 084de1
 * Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
Packit Service 084de1
 *
Packit Service 084de1
 * Licensed under the OpenSSL license (the "License").  You may not use
Packit Service 084de1
 * this file except in compliance with the License.  You can obtain a copy
Packit Service 084de1
 * in the file LICENSE in the source distribution or at
Packit Service 084de1
 * https://www.openssl.org/source/license.html
Packit Service 084de1
 */
Packit Service 084de1
Packit Service 084de1
#include <stdio.h>
Packit Service 084de1
#include "internal/cryptlib.h"
Packit Service 084de1
#include <openssl/x509.h>
Packit Service 084de1
#include <openssl/x509v3.h>
Packit Service 084de1
#include <openssl/evp.h>
Packit Service 084de1
#include <openssl/err.h>
Packit Service 084de1
#include "crypto/poly1305.h"
Packit Service 084de1
#include "poly1305_local.h"
Packit Service 084de1
#include "crypto/evp.h"
Packit Service 084de1
Packit Service 084de1
/* POLY1305 pkey context structure */
Packit Service 084de1
Packit Service 084de1
typedef struct {
Packit Service 084de1
    ASN1_OCTET_STRING ktmp;     /* Temp storage for key */
Packit Service 084de1
    POLY1305 ctx;
Packit Service 084de1
} POLY1305_PKEY_CTX;
Packit Service 084de1
Packit Service 084de1
static int pkey_poly1305_init(EVP_PKEY_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx;
Packit Service 084de1
Packit Service 084de1
    if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) {
Packit Service 084de1
        CRYPTOerr(CRYPTO_F_PKEY_POLY1305_INIT, ERR_R_MALLOC_FAILURE);
Packit Service 084de1
        return 0;
Packit Service 084de1
    }
Packit Service 084de1
    pctx->ktmp.type = V_ASN1_OCTET_STRING;
Packit Service 084de1
Packit Service 084de1
    EVP_PKEY_CTX_set_data(ctx, pctx);
Packit Service 084de1
    EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static void pkey_poly1305_cleanup(EVP_PKEY_CTX *ctx)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
Packit Service 084de1
Packit Service 084de1
    if (pctx != NULL) {
Packit Service 084de1
        OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
Packit Service 084de1
        OPENSSL_clear_free(pctx, sizeof(*pctx));
Packit Service 084de1
        EVP_PKEY_CTX_set_data(ctx, NULL);
Packit Service 084de1
    }
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int pkey_poly1305_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *sctx, *dctx;
Packit Service 084de1
Packit Service 084de1
    /* allocate memory for dst->data and a new POLY1305_CTX in dst->data->ctx */
Packit Service 084de1
    if (!pkey_poly1305_init(dst))
Packit Service 084de1
        return 0;
Packit Service 084de1
    sctx = EVP_PKEY_CTX_get_data(src);
Packit Service 084de1
    dctx = EVP_PKEY_CTX_get_data(dst);
Packit Service 084de1
    if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
Packit Service 084de1
        !ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
Packit Service 084de1
        /* cleanup and free the POLY1305_PKEY_CTX in dst->data */
Packit Service 084de1
        pkey_poly1305_cleanup(dst);
Packit Service 084de1
        return 0;
Packit Service 084de1
    }
Packit Service 084de1
    memcpy(&dctx->ctx, &sctx->ctx, sizeof(POLY1305));
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int pkey_poly1305_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
Packit Service 084de1
{
Packit Service 084de1
    ASN1_OCTET_STRING *key;
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
Packit Service 084de1
Packit Service 084de1
    if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
Packit Service 084de1
        return 0;
Packit Service 084de1
    key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
Packit Service 084de1
    if (key == NULL)
Packit Service 084de1
        return 0;
Packit Service 084de1
    return EVP_PKEY_assign_POLY1305(pkey, key);
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
Packit Service 084de1
Packit Service 084de1
    Poly1305_Update(&pctx->ctx, data, count);
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int poly1305_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = ctx->data;
Packit Service 084de1
    ASN1_OCTET_STRING *key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
Packit Service 084de1
Packit Service 084de1
    if (key->length != POLY1305_KEY_SIZE)
Packit Service 084de1
        return 0;
Packit Service 084de1
    EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
Packit Service 084de1
    EVP_MD_CTX_set_update_fn(mctx, int_update);
Packit Service 084de1
    Poly1305_Init(&pctx->ctx, key->data);
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
static int poly1305_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
Packit Service 084de1
                            EVP_MD_CTX *mctx)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = ctx->data;
Packit Service 084de1
Packit Service 084de1
    *siglen = POLY1305_DIGEST_SIZE;
Packit Service 084de1
    if (sig != NULL)
Packit Service 084de1
        Poly1305_Final(&pctx->ctx, sig);
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int pkey_poly1305_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
Packit Service 084de1
{
Packit Service 084de1
    POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
Packit Service 084de1
    const unsigned char *key;
Packit Service 084de1
    size_t len;
Packit Service 084de1
Packit Service 084de1
    switch (type) {
Packit Service 084de1
Packit Service 084de1
    case EVP_PKEY_CTRL_MD:
Packit Service 084de1
        /* ignore */
Packit Service 084de1
        break;
Packit Service 084de1
Packit Service 084de1
    case EVP_PKEY_CTRL_SET_MAC_KEY:
Packit Service 084de1
    case EVP_PKEY_CTRL_DIGESTINIT:
Packit Service 084de1
        if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
Packit Service 084de1
            /* user explicitly setting the key */
Packit Service 084de1
            key = p2;
Packit Service 084de1
            len = p1;
Packit Service 084de1
        } else {
Packit Service 084de1
            /* user indirectly setting the key via EVP_DigestSignInit */
Packit Service 084de1
            key = EVP_PKEY_get0_poly1305(EVP_PKEY_CTX_get0_pkey(ctx), &len;;
Packit Service 084de1
        }
Packit Service 084de1
        if (key == NULL || len != POLY1305_KEY_SIZE ||
Packit Service 084de1
            !ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
Packit Service 084de1
            return 0;
Packit Service 084de1
        Poly1305_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp));
Packit Service 084de1
        break;
Packit Service 084de1
Packit Service 084de1
    default:
Packit Service 084de1
        return -2;
Packit Service 084de1
Packit Service 084de1
    }
Packit Service 084de1
    return 1;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
static int pkey_poly1305_ctrl_str(EVP_PKEY_CTX *ctx,
Packit Service 084de1
                                  const char *type, const char *value)
Packit Service 084de1
{
Packit Service 084de1
    if (value == NULL)
Packit Service 084de1
        return 0;
Packit Service 084de1
    if (strcmp(type, "key") == 0)
Packit Service 084de1
        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
Packit Service 084de1
    if (strcmp(type, "hexkey") == 0)
Packit Service 084de1
        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
Packit Service 084de1
    return -2;
Packit Service 084de1
}
Packit Service 084de1
Packit Service 084de1
const EVP_PKEY_METHOD poly1305_pkey_meth = {
Packit Service 084de1
    EVP_PKEY_POLY1305,
Packit Service 084de1
    EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
Packit Service 084de1
    pkey_poly1305_init,
Packit Service 084de1
    pkey_poly1305_copy,
Packit Service 084de1
    pkey_poly1305_cleanup,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0,
Packit Service 084de1
    pkey_poly1305_keygen,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    poly1305_signctx_init,
Packit Service 084de1
    poly1305_signctx,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    0, 0,
Packit Service 084de1
Packit Service 084de1
    pkey_poly1305_ctrl,
Packit Service 084de1
    pkey_poly1305_ctrl_str
Packit Service 084de1
};
Packit Service 084de1
Packit Service 084de1
const EVP_PKEY_METHOD *poly1305_pkey_method(void)
Packit Service 084de1
{
Packit Service 084de1
    return &poly1305_pkey_meth;
Packit Service 084de1
}