1238384Sjkim/* pmeth_gn.c */
2238384Sjkim/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3238384Sjkim * project 2006.
4238384Sjkim */
5238384Sjkim/* ====================================================================
6238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10238384Sjkim * are met:
11238384Sjkim *
12238384Sjkim * 1. Redistributions of source code must retain the above copyright
13238384Sjkim *    notice, this list of conditions and the following disclaimer.
14238384Sjkim *
15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
16238384Sjkim *    notice, this list of conditions and the following disclaimer in
17238384Sjkim *    the documentation and/or other materials provided with the
18238384Sjkim *    distribution.
19238384Sjkim *
20238384Sjkim * 3. All advertising materials mentioning features or use of this
21238384Sjkim *    software must display the following acknowledgment:
22238384Sjkim *    "This product includes software developed by the OpenSSL Project
23238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24238384Sjkim *
25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26238384Sjkim *    endorse or promote products derived from this software without
27238384Sjkim *    prior written permission. For written permission, please contact
28238384Sjkim *    licensing@OpenSSL.org.
29238384Sjkim *
30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
31238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
32238384Sjkim *    permission of the OpenSSL Project.
33238384Sjkim *
34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
35238384Sjkim *    acknowledgment:
36238384Sjkim *    "This product includes software developed by the OpenSSL Project
37238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38238384Sjkim *
39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
51238384Sjkim * ====================================================================
52238384Sjkim *
53238384Sjkim * This product includes cryptographic software written by Eric Young
54238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
55238384Sjkim * Hudson (tjh@cryptsoft.com).
56238384Sjkim *
57238384Sjkim */
58238384Sjkim
59238384Sjkim#include <stdio.h>
60238384Sjkim#include <stdlib.h>
61238384Sjkim#include "cryptlib.h"
62238384Sjkim#include <openssl/objects.h>
63238384Sjkim#include <openssl/evp.h>
64238384Sjkim#include <openssl/bn.h>
65238384Sjkim#include "evp_locl.h"
66238384Sjkim
67238384Sjkimint EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
68238384Sjkim	{
69238384Sjkim	int ret;
70238384Sjkim	if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen)
71238384Sjkim		{
72238384Sjkim		EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT,
73238384Sjkim			EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
74238384Sjkim		return -2;
75238384Sjkim		}
76238384Sjkim	ctx->operation = EVP_PKEY_OP_PARAMGEN;
77238384Sjkim	if (!ctx->pmeth->paramgen_init)
78238384Sjkim		return 1;
79238384Sjkim	ret = ctx->pmeth->paramgen_init(ctx);
80238384Sjkim	if (ret <= 0)
81238384Sjkim		ctx->operation = EVP_PKEY_OP_UNDEFINED;
82238384Sjkim	return ret;
83238384Sjkim	}
84238384Sjkim
85238384Sjkimint EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
86238384Sjkim	{
87238384Sjkim	int ret;
88238384Sjkim	if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen)
89238384Sjkim		{
90238384Sjkim		EVPerr(EVP_F_EVP_PKEY_PARAMGEN,
91238384Sjkim			EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
92238384Sjkim		return -2;
93238384Sjkim		}
94238384Sjkim
95238384Sjkim	if (ctx->operation != EVP_PKEY_OP_PARAMGEN)
96238384Sjkim		{
97238384Sjkim		EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED);
98238384Sjkim		return -1;
99238384Sjkim		}
100238384Sjkim
101238384Sjkim	if (!ppkey)
102238384Sjkim		return -1;
103238384Sjkim
104238384Sjkim	if (!*ppkey)
105238384Sjkim		*ppkey = EVP_PKEY_new();
106238384Sjkim
107238384Sjkim	ret = ctx->pmeth->paramgen(ctx, *ppkey);
108238384Sjkim	if (ret <= 0)
109238384Sjkim		{
110238384Sjkim		EVP_PKEY_free(*ppkey);
111238384Sjkim		*ppkey = NULL;
112238384Sjkim		}
113238384Sjkim	return ret;
114238384Sjkim	}
115238384Sjkim
116238384Sjkimint EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
117238384Sjkim	{
118238384Sjkim	int ret;
119238384Sjkim	if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen)
120238384Sjkim		{
121238384Sjkim		EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT,
122238384Sjkim			EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
123238384Sjkim		return -2;
124238384Sjkim		}
125238384Sjkim	ctx->operation = EVP_PKEY_OP_KEYGEN;
126238384Sjkim	if (!ctx->pmeth->keygen_init)
127238384Sjkim		return 1;
128238384Sjkim	ret = ctx->pmeth->keygen_init(ctx);
129238384Sjkim	if (ret <= 0)
130238384Sjkim		ctx->operation = EVP_PKEY_OP_UNDEFINED;
131238384Sjkim	return ret;
132238384Sjkim	}
133238384Sjkim
134238384Sjkimint EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
135238384Sjkim	{
136238384Sjkim	int ret;
137238384Sjkim
138238384Sjkim	if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen)
139238384Sjkim		{
140238384Sjkim		EVPerr(EVP_F_EVP_PKEY_KEYGEN,
141238384Sjkim			EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
142238384Sjkim		return -2;
143238384Sjkim		}
144238384Sjkim	if (ctx->operation != EVP_PKEY_OP_KEYGEN)
145238384Sjkim		{
146238384Sjkim		EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED);
147238384Sjkim		return -1;
148238384Sjkim		}
149238384Sjkim
150238384Sjkim	if (!ppkey)
151238384Sjkim		return -1;
152238384Sjkim
153238384Sjkim	if (!*ppkey)
154238384Sjkim		*ppkey = EVP_PKEY_new();
155238384Sjkim
156238384Sjkim	ret = ctx->pmeth->keygen(ctx, *ppkey);
157238384Sjkim	if (ret <= 0)
158238384Sjkim		{
159238384Sjkim		EVP_PKEY_free(*ppkey);
160238384Sjkim		*ppkey = NULL;
161238384Sjkim		}
162238384Sjkim	return ret;
163238384Sjkim	}
164238384Sjkim
165238384Sjkimvoid EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
166238384Sjkim	{
167238384Sjkim	ctx->pkey_gencb = cb;
168238384Sjkim	}
169238384Sjkim
170238384SjkimEVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
171238384Sjkim	{
172238384Sjkim	return ctx->pkey_gencb;
173238384Sjkim	}
174238384Sjkim
175238384Sjkim/* "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB
176238384Sjkim * style callbacks.
177238384Sjkim */
178238384Sjkim
179238384Sjkimstatic int trans_cb(int a, int b, BN_GENCB *gcb)
180238384Sjkim	{
181238384Sjkim	EVP_PKEY_CTX *ctx = gcb->arg;
182238384Sjkim	ctx->keygen_info[0] = a;
183238384Sjkim	ctx->keygen_info[1] = b;
184238384Sjkim	return ctx->pkey_gencb(ctx);
185238384Sjkim	}
186238384Sjkim
187238384Sjkimvoid evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
188238384Sjkim	{
189238384Sjkim	BN_GENCB_set(cb, trans_cb, ctx)
190238384Sjkim	}
191238384Sjkim
192238384Sjkimint EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
193238384Sjkim	{
194238384Sjkim	if (idx == -1)
195238384Sjkim		return ctx->keygen_info_count;
196238384Sjkim	if (idx < 0 || idx > ctx->keygen_info_count)
197238384Sjkim		return 0;
198238384Sjkim	return ctx->keygen_info[idx];
199238384Sjkim	}
200238384Sjkim
201238384SjkimEVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
202238384Sjkim				const unsigned char *key, int keylen)
203238384Sjkim	{
204238384Sjkim	EVP_PKEY_CTX *mac_ctx = NULL;
205238384Sjkim	EVP_PKEY *mac_key = NULL;
206238384Sjkim	mac_ctx = EVP_PKEY_CTX_new_id(type, e);
207238384Sjkim	if (!mac_ctx)
208238384Sjkim		return NULL;
209238384Sjkim	if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
210238384Sjkim		goto merr;
211238384Sjkim	if (EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
212238384Sjkim				EVP_PKEY_CTRL_SET_MAC_KEY,
213238384Sjkim				keylen, (void *)key) <= 0)
214238384Sjkim		goto merr;
215238384Sjkim	if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
216238384Sjkim		goto merr;
217238384Sjkim	merr:
218238384Sjkim	if (mac_ctx)
219238384Sjkim		EVP_PKEY_CTX_free(mac_ctx);
220238384Sjkim	return mac_key;
221238384Sjkim	}
222