1238384Sjkim/* pmeth_gn.c */
2280297Sjkim/*
3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4280297Sjkim * 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
14280297Sjkim *    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)
69280297Sjkim{
70280297Sjkim    int ret;
71280297Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
72280297Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT,
73280297Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
74280297Sjkim        return -2;
75280297Sjkim    }
76280297Sjkim    ctx->operation = EVP_PKEY_OP_PARAMGEN;
77280297Sjkim    if (!ctx->pmeth->paramgen_init)
78280297Sjkim        return 1;
79280297Sjkim    ret = ctx->pmeth->paramgen_init(ctx);
80280297Sjkim    if (ret <= 0)
81280297Sjkim        ctx->operation = EVP_PKEY_OP_UNDEFINED;
82280297Sjkim    return ret;
83280297Sjkim}
84238384Sjkim
85238384Sjkimint EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
86280297Sjkim{
87280297Sjkim    int ret;
88280297Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
89280297Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN,
90280297Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
91280297Sjkim        return -2;
92280297Sjkim    }
93238384Sjkim
94280297Sjkim    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
95280297Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED);
96280297Sjkim        return -1;
97280297Sjkim    }
98238384Sjkim
99291719Sjkim    if (ppkey == NULL)
100280297Sjkim        return -1;
101238384Sjkim
102291719Sjkim    if (*ppkey == NULL)
103280297Sjkim        *ppkey = EVP_PKEY_new();
104238384Sjkim
105291719Sjkim    if (*ppkey == NULL) {
106291719Sjkim        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE);
107291719Sjkim        return -1;
108291719Sjkim    }
109291719Sjkim
110280297Sjkim    ret = ctx->pmeth->paramgen(ctx, *ppkey);
111280297Sjkim    if (ret <= 0) {
112280297Sjkim        EVP_PKEY_free(*ppkey);
113280297Sjkim        *ppkey = NULL;
114280297Sjkim    }
115280297Sjkim    return ret;
116280297Sjkim}
117238384Sjkim
118238384Sjkimint EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
119280297Sjkim{
120280297Sjkim    int ret;
121280297Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
122280297Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT,
123280297Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
124280297Sjkim        return -2;
125280297Sjkim    }
126280297Sjkim    ctx->operation = EVP_PKEY_OP_KEYGEN;
127280297Sjkim    if (!ctx->pmeth->keygen_init)
128280297Sjkim        return 1;
129280297Sjkim    ret = ctx->pmeth->keygen_init(ctx);
130280297Sjkim    if (ret <= 0)
131280297Sjkim        ctx->operation = EVP_PKEY_OP_UNDEFINED;
132280297Sjkim    return ret;
133280297Sjkim}
134238384Sjkim
135238384Sjkimint EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
136280297Sjkim{
137280297Sjkim    int ret;
138238384Sjkim
139280297Sjkim    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
140280297Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN,
141280297Sjkim               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
142280297Sjkim        return -2;
143280297Sjkim    }
144280297Sjkim    if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
145280297Sjkim        EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED);
146280297Sjkim        return -1;
147280297Sjkim    }
148238384Sjkim
149280297Sjkim    if (!ppkey)
150280297Sjkim        return -1;
151238384Sjkim
152306195Sjkim    if (*ppkey == NULL)
153280297Sjkim        *ppkey = EVP_PKEY_new();
154306195Sjkim    if (*ppkey == NULL)
155306195Sjkim        return -1;
156238384Sjkim
157280297Sjkim    ret = ctx->pmeth->keygen(ctx, *ppkey);
158280297Sjkim    if (ret <= 0) {
159280297Sjkim        EVP_PKEY_free(*ppkey);
160280297Sjkim        *ppkey = NULL;
161280297Sjkim    }
162280297Sjkim    return ret;
163280297Sjkim}
164238384Sjkim
165238384Sjkimvoid EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
166280297Sjkim{
167280297Sjkim    ctx->pkey_gencb = cb;
168280297Sjkim}
169238384Sjkim
170238384SjkimEVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
171280297Sjkim{
172280297Sjkim    return ctx->pkey_gencb;
173280297Sjkim}
174238384Sjkim
175280297Sjkim/*
176280297Sjkim * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
177280297Sjkim * callbacks.
178238384Sjkim */
179238384Sjkim
180238384Sjkimstatic int trans_cb(int a, int b, BN_GENCB *gcb)
181280297Sjkim{
182280297Sjkim    EVP_PKEY_CTX *ctx = gcb->arg;
183280297Sjkim    ctx->keygen_info[0] = a;
184280297Sjkim    ctx->keygen_info[1] = b;
185280297Sjkim    return ctx->pkey_gencb(ctx);
186280297Sjkim}
187238384Sjkim
188238384Sjkimvoid evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
189280297Sjkim{
190280297Sjkim    BN_GENCB_set(cb, trans_cb, ctx)
191280297Sjkim}
192238384Sjkim
193238384Sjkimint EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
194280297Sjkim{
195280297Sjkim    if (idx == -1)
196280297Sjkim        return ctx->keygen_info_count;
197280297Sjkim    if (idx < 0 || idx > ctx->keygen_info_count)
198280297Sjkim        return 0;
199280297Sjkim    return ctx->keygen_info[idx];
200280297Sjkim}
201238384Sjkim
202238384SjkimEVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
203280297Sjkim                               const unsigned char *key, int keylen)
204280297Sjkim{
205280297Sjkim    EVP_PKEY_CTX *mac_ctx = NULL;
206280297Sjkim    EVP_PKEY *mac_key = NULL;
207280297Sjkim    mac_ctx = EVP_PKEY_CTX_new_id(type, e);
208280297Sjkim    if (!mac_ctx)
209280297Sjkim        return NULL;
210280297Sjkim    if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
211280297Sjkim        goto merr;
212280297Sjkim    if (EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
213280297Sjkim                          EVP_PKEY_CTRL_SET_MAC_KEY,
214280297Sjkim                          keylen, (void *)key) <= 0)
215280297Sjkim        goto merr;
216280297Sjkim    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
217280297Sjkim        goto merr;
218280297Sjkim merr:
219280297Sjkim    if (mac_ctx)
220280297Sjkim        EVP_PKEY_CTX_free(mac_ctx);
221280297Sjkim    return mac_key;
222280297Sjkim}
223