1238384Sjkim/* pmeth_gn.c */
2280304Sjkim/*
3280304Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280304Sjkim * 2006.
5238384Sjkim */
6238384Sjkim/* ====================================================================
7238384Sjkim * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
8238384Sjkim *
9238384Sjkim * Redistribution and use in source and binary forms, with or without
10238384Sjkim * modification, are permitted provided that the following conditions
11238384Sjkim * are met:
12238384Sjkim *
13238384Sjkim * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
15238384Sjkim *
16238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright
17238384Sjkim *    notice, this list of conditions and the following disclaimer in
18238384Sjkim *    the documentation and/or other materials provided with the
19238384Sjkim *    distribution.
20238384Sjkim *
21238384Sjkim * 3. All advertising materials mentioning features or use of this
22238384Sjkim *    software must display the following acknowledgment:
23238384Sjkim *    "This product includes software developed by the OpenSSL Project
24238384Sjkim *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25238384Sjkim *
26238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27238384Sjkim *    endorse or promote products derived from this software without
28238384Sjkim *    prior written permission. For written permission, please contact
29238384Sjkim *    licensing@OpenSSL.org.
30238384Sjkim *
31238384Sjkim * 5. Products derived from this software may not be called "OpenSSL"
32238384Sjkim *    nor may "OpenSSL" appear in their names without prior written
33238384Sjkim *    permission of the OpenSSL Project.
34238384Sjkim *
35238384Sjkim * 6. Redistributions of any form whatsoever must retain the following
36238384Sjkim *    acknowledgment:
37238384Sjkim *    "This product includes software developed by the OpenSSL Project
38238384Sjkim *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39238384Sjkim *
40238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43238384Sjkim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE.
52238384Sjkim * ====================================================================
53238384Sjkim *
54238384Sjkim * This product includes cryptographic software written by Eric Young
55238384Sjkim * (eay@cryptsoft.com).  This product includes software written by Tim
56238384Sjkim * Hudson (tjh@cryptsoft.com).
57238384Sjkim *
58238384Sjkim */
59238384Sjkim
60238384Sjkim#include <stdio.h>
61238384Sjkim#include <stdlib.h>
62238384Sjkim#include "cryptlib.h"
63238384Sjkim#include <openssl/objects.h>
64238384Sjkim#include <openssl/evp.h>
65238384Sjkim#include <openssl/bn.h>
66238384Sjkim#include "evp_locl.h"
67238384Sjkim
68238384Sjkimint EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
69280304Sjkim{
70280304Sjkim    int ret;
71280304Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
72280304Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT,
73280304Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
74280304Sjkim        return -2;
75280304Sjkim    }
76280304Sjkim    ctx->operation = EVP_PKEY_OP_PARAMGEN;
77280304Sjkim    if (!ctx->pmeth->paramgen_init)
78280304Sjkim        return 1;
79280304Sjkim    ret = ctx->pmeth->paramgen_init(ctx);
80280304Sjkim    if (ret <= 0)
81280304Sjkim        ctx->operation = EVP_PKEY_OP_UNDEFINED;
82280304Sjkim    return ret;
83280304Sjkim}
84238384Sjkim
85238384Sjkimint EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
86280304Sjkim{
87280304Sjkim    int ret;
88280304Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
89280304Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN,
90280304Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
91280304Sjkim        return -2;
92280304Sjkim    }
93238384Sjkim
94280304Sjkim    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
95280304Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED);
96280304Sjkim        return -1;
97280304Sjkim    }
98238384Sjkim
99291721Sjkim    if (ppkey == NULL)
100280304Sjkim        return -1;
101238384Sjkim
102291721Sjkim    if (*ppkey == NULL)
103280304Sjkim        *ppkey = EVP_PKEY_new();
104238384Sjkim
105291721Sjkim    if (*ppkey == NULL) {
106291721Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE);
107291721Sjkim        return -1;
108291721Sjkim    }
109291721Sjkim
110280304Sjkim    ret = ctx->pmeth->paramgen(ctx, *ppkey);
111280304Sjkim    if (ret <= 0) {
112280304Sjkim        EVP_PKEY_free(*ppkey);
113280304Sjkim        *ppkey = NULL;
114280304Sjkim    }
115280304Sjkim    return ret;
116280304Sjkim}
117238384Sjkim
118238384Sjkimint EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
119280304Sjkim{
120280304Sjkim    int ret;
121280304Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
122280304Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT,
123280304Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
124280304Sjkim        return -2;
125280304Sjkim    }
126280304Sjkim    ctx->operation = EVP_PKEY_OP_KEYGEN;
127280304Sjkim    if (!ctx->pmeth->keygen_init)
128280304Sjkim        return 1;
129280304Sjkim    ret = ctx->pmeth->keygen_init(ctx);
130280304Sjkim    if (ret <= 0)
131280304Sjkim        ctx->operation = EVP_PKEY_OP_UNDEFINED;
132280304Sjkim    return ret;
133280304Sjkim}
134238384Sjkim
135238384Sjkimint EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
136280304Sjkim{
137280304Sjkim    int ret;
138238384Sjkim
139280304Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
140280304Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN,
141280304Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
142280304Sjkim        return -2;
143280304Sjkim    }
144280304Sjkim    if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
145280304Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED);
146280304Sjkim        return -1;
147280304Sjkim    }
148238384Sjkim
149280304Sjkim    if (!ppkey)
150280304Sjkim        return -1;
151238384Sjkim
152280304Sjkim    if (!*ppkey)
153280304Sjkim        *ppkey = EVP_PKEY_new();
154238384Sjkim
155280304Sjkim    ret = ctx->pmeth->keygen(ctx, *ppkey);
156280304Sjkim    if (ret <= 0) {
157280304Sjkim        EVP_PKEY_free(*ppkey);
158280304Sjkim        *ppkey = NULL;
159280304Sjkim    }
160280304Sjkim    return ret;
161280304Sjkim}
162238384Sjkim
163238384Sjkimvoid EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
164280304Sjkim{
165280304Sjkim    ctx->pkey_gencb = cb;
166280304Sjkim}
167238384Sjkim
168238384SjkimEVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
169280304Sjkim{
170280304Sjkim    return ctx->pkey_gencb;
171280304Sjkim}
172238384Sjkim
173280304Sjkim/*
174280304Sjkim * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
175280304Sjkim * callbacks.
176238384Sjkim */
177238384Sjkim
178238384Sjkimstatic int trans_cb(int a, int b, BN_GENCB *gcb)
179280304Sjkim{
180280304Sjkim    EVP_PKEY_CTX *ctx = gcb->arg;
181280304Sjkim    ctx->keygen_info[0] = a;
182280304Sjkim    ctx->keygen_info[1] = b;
183280304Sjkim    return ctx->pkey_gencb(ctx);
184280304Sjkim}
185238384Sjkim
186238384Sjkimvoid evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
187280304Sjkim{
188280304Sjkim    BN_GENCB_set(cb, trans_cb, ctx)
189280304Sjkim}
190238384Sjkim
191238384Sjkimint EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
192280304Sjkim{
193280304Sjkim    if (idx == -1)
194280304Sjkim        return ctx->keygen_info_count;
195280304Sjkim    if (idx < 0 || idx > ctx->keygen_info_count)
196280304Sjkim        return 0;
197280304Sjkim    return ctx->keygen_info[idx];
198280304Sjkim}
199238384Sjkim
200238384SjkimEVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
201280304Sjkim                               const unsigned char *key, int keylen)
202280304Sjkim{
203280304Sjkim    EVP_PKEY_CTX *mac_ctx = NULL;
204280304Sjkim    EVP_PKEY *mac_key = NULL;
205280304Sjkim    mac_ctx = EVP_PKEY_CTX_new_id(type, e);
206280304Sjkim    if (!mac_ctx)
207280304Sjkim        return NULL;
208280304Sjkim    if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
209280304Sjkim        goto merr;
210280304Sjkim    if (EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
211280304Sjkim                          EVP_PKEY_CTRL_SET_MAC_KEY,
212280304Sjkim                          keylen, (void *)key) <= 0)
213280304Sjkim        goto merr;
214280304Sjkim    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
215280304Sjkim        goto merr;
216280304Sjkim merr:
217280304Sjkim    if (mac_ctx)
218280304Sjkim        EVP_PKEY_CTX_free(mac_ctx);
219280304Sjkim    return mac_key;
220280304Sjkim}
221