195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * project 2006. 395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */ 495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* ==================================================================== 595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without 895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions 995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met: 1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright 1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer. 1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright 1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * notice, this list of conditions and the following disclaimer in 1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the documentation and/or other materials provided with the 1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * distribution. 1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this 2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * software must display the following acknowledgment: 2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * endorse or promote products derived from this software without 2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * prior written permission. For written permission, please contact 2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * licensing@OpenSSL.org. 2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5. Products derived from this software may not be called "OpenSSL" 3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * nor may "OpenSSL" appear in their names without prior written 3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * permission of the OpenSSL Project. 3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 6. Redistributions of any form whatsoever must retain the following 3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * acknowledgment: 3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * "This product includes software developed by the OpenSSL Project 3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ==================================================================== 5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This product includes cryptographic software written by Eric Young 5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (eay@cryptsoft.com). This product includes software written by Tim 5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Hudson (tjh@cryptsoft.com). */ 5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/evp.h> 5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1.h> 5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/bn.h> 6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/buf.h> 6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/digest.h> 6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ec.h> 6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ec_key.h> 6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ecdh.h> 6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ecdsa.h> 6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h> 6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h> 6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/obj.h> 6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "internal.h" 7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "../ec/internal.h" 7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleytypedef struct { 7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Key and paramgen group */ 7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_GROUP *gen_group; 7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* message digest */ 7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_MD *md; 7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Duplicate key if custom cofactor needed */ 8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *co_key; 8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Cofactor mode */ 8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley signed char cofactor_mode; 8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* KDF (if any) to use for ECDH */ 8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley char kdf_type; 8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Message digest to use for key derivation */ 8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EVP_MD *kdf_md; 8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* User key material */ 8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned char *kdf_ukm; 8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t kdf_ukmlen; 9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* KDF output length */ 9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t kdf_outlen; 9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} EC_PKEY_CTX; 9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_init(EVP_PKEY_CTX *ctx) { 9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx; 9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX)); 9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!dctx) { 9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley memset(dctx, 0, sizeof(EC_PKEY_CTX)); 10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->cofactor_mode = -1; 10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE; 10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ctx->data = dctx; 10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) { 11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx, *sctx; 11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pkey_ec_init(dst)) { 11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley sctx = src->data; 11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx = dst->data; 11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (sctx->gen_group) { 11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->gen_group = EC_GROUP_dup(sctx->gen_group); 12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!dctx->gen_group) { 12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->md = sctx->md; 12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (sctx->co_key) { 12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->co_key = EC_KEY_dup(sctx->co_key); 12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!dctx->co_key) { 12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_type = sctx->kdf_type; 13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_md = sctx->kdf_md; 13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_outlen = sctx->kdf_outlen; 13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (sctx->kdf_ukm) { 13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen); 13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!dctx->kdf_ukm) { 13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukm = NULL; 14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukmlen = sctx->kdf_ukmlen; 14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) { 14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!dctx) { 15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return; 15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->gen_group) { 15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_GROUP_free(dctx->gen_group); 15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->co_key) { 15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY_free(dctx->co_key); 15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->kdf_ukm) { 16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(dctx->kdf_ukm); 16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(dctx); 16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen, 16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const uint8_t *tbs, size_t tbslen) { 1675129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley int type; 16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley unsigned int sltmp; 16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *ec = ctx->pkey->pkey.ec; 17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!sig) { 17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *siglen = ECDSA_size(ec); 17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else if (*siglen < (size_t)ECDSA_size(ec)) { 17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_sign, EVP_R_BUFFER_TOO_SMALL); 17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley type = NID_sha1; 18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->md) { 18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley type = EVP_MD_type(dctx->md); 18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 1855129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley if (!ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec)) { 1865129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley return 0; 18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *siglen = (size_t)sltmp; 18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen, 19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const uint8_t *tbs, size_t tbslen) { 19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int type; 19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *ec = ctx->pkey->pkey.ec; 19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley type = NID_sha1; 19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->md) { 20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley type = EVP_MD_type(dctx->md); 20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ECDSA_verify(type, tbs, tbslen, sig, siglen, ec); 20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key, 20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t *keylen) { 20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret; 20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t outlen; 21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EC_POINT *pubkey = NULL; 21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *eckey; 21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ctx->pkey || !ctx->peerkey) { 21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_derive, EVP_R_KEYS_NOT_SET); 21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec; 22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!key) { 22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley const EC_GROUP *group; 22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley group = EC_KEY_get0_group(eckey); 22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *keylen = (EC_GROUP_get_degree(group) + 7) / 8; 22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec); 22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is 23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * not an error, the result is truncated. */ 23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley outlen = *keylen; 23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0); 23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ret < 0) { 2365129e2d69582c0c54a335eb7e0bc794a02418403Adam Langley return 0; 23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *keylen = ret; 23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, uint8_t *key, 24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t *keylen) { 24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley uint8_t *ktmp = NULL; 24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley size_t ktmplen; 24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int rv = 0; 24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) { 25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return pkey_ec_derive(ctx, key, keylen); 25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!key) { 25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *keylen = dctx->kdf_outlen; 25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (*keylen != dctx->kdf_outlen || 25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley !pkey_ec_derive(ctx, NULL, &ktmplen)) { 25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ktmp = OPENSSL_malloc(ktmplen); 26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ktmp) { 26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) { 26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm, 26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukmlen, dctx->kdf_md)) { 27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley goto err; 27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley rv = 1; 27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr: 27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ktmp) { 27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_cleanse(ktmp, ktmplen); 27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(ktmp); 27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return rv; 28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) { 28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_GROUP *group; 28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley switch (type) { 28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley group = EC_GROUP_new_by_curve_name(p1); 28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (group == NULL) { 29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_CURVE); 29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->gen_group) 29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_GROUP_free(dctx->gen_group); 29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->gen_group = group; 29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_EC_KDF_TYPE: 29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (p1 == -2) 30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return dctx->kdf_type; 30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62) 30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -2; 30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_type = p1; 30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_EC_KDF_MD: 30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_md = p2; 30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_GET_EC_KDF_MD: 31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *(const EVP_MD **)p2 = dctx->kdf_md; 31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_EC_KDF_OUTLEN: 31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (p1 <= 0) 31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -2; 31795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_outlen = (size_t)p1; 31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN: 32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *(int *)p2 = dctx->kdf_outlen; 32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_EC_KDF_UKM: 32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->kdf_ukm) 32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_free(dctx->kdf_ukm); 32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukm = p2; 32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (p2) 32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukmlen = p1; 33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley else 33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->kdf_ukmlen = 0; 33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_GET_EC_KDF_UKM: 33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *(unsigned char **)p2 = dctx->kdf_ukm; 33695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return dctx->kdf_ukmlen; 33795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 33895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_MD: 33995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 && 34095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 && 34195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_type((const EVP_MD *)p2) != NID_sha224 && 34295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_type((const EVP_MD *)p2) != NID_sha256 && 34395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_type((const EVP_MD *)p2) != NID_sha384 && 34495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_MD_type((const EVP_MD *)p2) != NID_sha512) { 34595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_DIGEST_TYPE); 34695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 34795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 34895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley dctx->md = p2; 34995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 35095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 35195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_GET_MD: 35295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *(const EVP_MD **)p2 = dctx->md; 35395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 35495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 35595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_PEER_KEY: 35695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Default behaviour is OK */ 35795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley case EVP_PKEY_CTRL_DIGESTINIT: 35895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 1; 35995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley default: 36195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return -2; 36295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 36395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 36495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 36595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { 36695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *ec = NULL; 36795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 36895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley int ret = 0; 36995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 37095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (dctx->gen_group == NULL) { 37195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_paramgen, EVP_R_NO_PARAMETERS_SET); 37295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 37395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 37495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ec = EC_KEY_new(); 37595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ec) { 37695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 37795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 37895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ret = EC_KEY_set_group(ec, dctx->gen_group); 37995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ret) { 38095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_PKEY_assign_EC_KEY(pkey, ec); 38195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 38295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY_free(ec); 38395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 38495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return ret; 38595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 38695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 38795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystatic int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { 38895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_KEY *ec = NULL; 38995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EC_PKEY_CTX *dctx = ctx->data; 39095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ctx->pkey == NULL && dctx->gen_group == NULL) { 39195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley OPENSSL_PUT_ERROR(EVP, pkey_ec_keygen, EVP_R_NO_PARAMETERS_SET); 39295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 39395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 39495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley ec = EC_KEY_new(); 39595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!ec) { 39695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 39795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 39895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_PKEY_assign_EC_KEY(pkey, ec); 39995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (ctx->pkey) { 40095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley /* Note: if error return, pkey is freed by parent routine */ 40195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) { 40295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 40395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 40495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } else { 40595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley if (!EC_KEY_set_group(ec, dctx->gen_group)) { 40695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return 0; 40795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 40895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley } 40995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley return EC_KEY_generate_key(pkey->pkey.ec); 41095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley} 41195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 41295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst EVP_PKEY_METHOD ec_pkey_meth = { 41395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley EVP_PKEY_EC, 0 /* flags */, pkey_ec_init, 41495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkey_ec_copy, pkey_ec_cleanup, 0 /* paramgen_init */, 41595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkey_ec_paramgen, 0 /* keygen_init */, pkey_ec_keygen, 41695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 0 /* sign_init */, pkey_ec_sign, 0 /* verify_init */, 41795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley pkey_ec_verify, 0 /* signctx_init */, 0 /* signctx */, 41895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 0 /* verifyctx_init */, 0 /* verifyctx */, 0 /* encrypt_init */, 41995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 0 /* encrypt */, 0 /* decrypt_init */, 0 /* decrypt */, 42095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley 0 /* derive_init */, pkey_ec_kdf_derive, pkey_ec_ctrl, 42195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}; 422