summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2006-04-11 13:28:52 +0000
committerDr. Stephen Henson <steve@openssl.org>2006-04-11 13:28:52 +0000
commitf5cda4cbb17c908ceef33f4f52d94e8e04b7c1ab (patch)
tree851abcd3b7178040056cbb1ce397bbc526774041 /crypto
parentf9a6348a537290f65fd76d945419a4c9bafff012 (diff)
downloadopenssl-new-f5cda4cbb17c908ceef33f4f52d94e8e04b7c1ab.tar.gz
Initial keygen support.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asn1/ameth_lib.c2
-rw-r--r--crypto/evp/Makefile4
-rw-r--r--crypto/evp/evp.h21
-rw-r--r--crypto/evp/evp_err.c4
-rw-r--r--crypto/evp/evp_locl.h14
-rw-r--r--crypto/evp/pmeth_gn.c193
-rw-r--r--crypto/evp/pmeth_lib.c45
-rw-r--r--crypto/rsa/rsa_pmeth.c37
8 files changed, 308 insertions, 12 deletions
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
index 14b5aa335b..4dd0dfa62b 100644
--- a/crypto/asn1/ameth_lib.c
+++ b/crypto/asn1/ameth_lib.c
@@ -160,6 +160,8 @@ const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(const char *str, int len)
{
int i;
const EVP_PKEY_ASN1_METHOD *ameth;
+ if (len == -1)
+ len = strlen(str);
for (i = 0; i < EVP_PKEY_asn1_get_count(); i++)
{
ameth = EVP_PKEY_asn1_get0(i);
diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile
index cad6e9a88a..9b8a57fc19 100644
--- a/crypto/evp/Makefile
+++ b/crypto/evp/Makefile
@@ -28,7 +28,7 @@ LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c \
bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
c_all.c c_allc.c c_alld.c evp_lib.c bio_ok.c \
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c \
- e_old.c pmeth_lib.c pmeth_fn.c
+ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c
LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \
e_des.o e_bf.o e_idea.o e_des3.o \
@@ -40,7 +40,7 @@ LIBOBJ= encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \
bio_md.o bio_b64.o bio_enc.o evp_err.o e_null.o \
c_all.o c_allc.o c_alld.o evp_lib.o bio_ok.o \
evp_pkey.o evp_pbe.o p5_crpt.o p5_crpt2.o \
- e_old.o pmeth_lib.o pmeth_fn.o
+ e_old.o pmeth_lib.o pmeth_fn.o pmeth_gn.o
SRC= $(LIBSRC)
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index 7d089fe931..6ad54647b9 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -937,7 +937,8 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
#define EVP_PKEY_ALG_CTRL 0x1000
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e);
-EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
@@ -945,6 +946,10 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value);
+void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
+void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
+void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
+void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
@@ -967,6 +972,16 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, int *outlen,
const unsigned char *in, int inlen);
+typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
+
+int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
+int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
+
+void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
+int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx);
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -1006,7 +1021,11 @@ void ERR_load_EVP_strings(void);
#define EVP_F_EVP_PKEY_GET1_ECDSA 130
#define EVP_F_EVP_PKEY_GET1_EC_KEY 131
#define EVP_F_EVP_PKEY_GET1_RSA 121
+#define EVP_F_EVP_PKEY_KEYGEN 146
+#define EVP_F_EVP_PKEY_KEYGEN_INIT 147
#define EVP_F_EVP_PKEY_NEW 106
+#define EVP_F_EVP_PKEY_PARAMGEN 148
+#define EVP_F_EVP_PKEY_PARAMGEN_INIT 149
#define EVP_F_EVP_PKEY_SIGN 140
#define EVP_F_EVP_PKEY_SIGN_INIT 141
#define EVP_F_EVP_PKEY_VERIFY 142
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 0f14fa8a7d..c3e51f89e0 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -100,7 +100,11 @@ static ERR_STRING_DATA EVP_str_functs[]=
{ERR_FUNC(EVP_F_EVP_PKEY_GET1_ECDSA), "EVP_PKEY_GET1_ECDSA"},
{ERR_FUNC(EVP_F_EVP_PKEY_GET1_EC_KEY), "EVP_PKEY_get1_EC_KEY"},
{ERR_FUNC(EVP_F_EVP_PKEY_GET1_RSA), "EVP_PKEY_get1_RSA"},
+{ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN), "EVP_PKEY_KEYGEN"},
+{ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN_INIT), "EVP_PKEY_KEYGEN_INIT"},
{ERR_FUNC(EVP_F_EVP_PKEY_NEW), "EVP_PKEY_new"},
+{ERR_FUNC(EVP_F_EVP_PKEY_PARAMGEN), "EVP_PKEY_PARAMGEN"},
+{ERR_FUNC(EVP_F_EVP_PKEY_PARAMGEN_INIT), "EVP_PKEY_PARAMGEN_INIT"},
{ERR_FUNC(EVP_F_EVP_PKEY_SIGN), "EVP_PKEY_sign"},
{ERR_FUNC(EVP_F_EVP_PKEY_SIGN_INIT), "EVP_PKEY_sign_init"},
{ERR_FUNC(EVP_F_EVP_PKEY_VERIFY), "EVP_PKEY_verify"},
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 983dae7845..3edfd9949f 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -235,7 +235,6 @@ const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
EVP_CIPHER_get_asn1_iv, \
NULL)
-
struct evp_pkey_ctx_st
{
/* Method associated with this operation */
@@ -246,6 +245,13 @@ struct evp_pkey_ctx_st
int operation;
/* Algorithm specific data */
void *data;
+ /* Application specific data */
+ void *app_data;
+ /* Keygen callback */
+ EVP_PKEY_gen_cb *pkey_gencb;
+ /* implementation specific keygen data */
+ int *keygen_info;
+ int keygen_info_count;
} /* EVP_PKEY_CTX */;
struct evp_pkey_method_st
@@ -257,10 +263,10 @@ struct evp_pkey_method_st
void (*cleanup)(EVP_PKEY_CTX *ctx);
int (*paramgen_init)(EVP_PKEY_CTX *ctx);
- int (*paramgen)(EVP_PKEY_CTX *ctx);
+ int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
int (*keygen_init)(EVP_PKEY_CTX *ctx);
- int (*keygen)(EVP_PKEY_CTX *ctx);
+ int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
int (*sign_init)(EVP_PKEY_CTX *ctx);
int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
@@ -296,3 +302,5 @@ struct evp_pkey_method_st
} /* EVP_PKEY_METHOD */;
+
+void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);
diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c
new file mode 100644
index 0000000000..4972d5e96d
--- /dev/null
+++ b/crypto/evp/pmeth_gn.c
@@ -0,0 +1,193 @@
+/* pmeth_gn.c */
+/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/objects.h>
+#include "cryptlib.h"
+#include <openssl/evp.h>
+#include "evp_locl.h"
+
+int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
+ {
+ int ret;
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen)
+ {
+ EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ ctx->operation = EVP_PKEY_OP_PARAMGEN;
+ if (!ctx->pmeth->paramgen_init)
+ return 1;
+ ret = ctx->pmeth->paramgen_init(ctx);
+ if (ret <= 0)
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return ret;
+ }
+
+int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+ {
+ int ret;
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen)
+ {
+ EVPerr(EVP_F_EVP_PKEY_PARAMGEN,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+
+ if (ctx->operation != EVP_PKEY_OP_PARAMGEN)
+ {
+ EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (!ppkey)
+ return -1;
+
+ if (!*ppkey)
+ *ppkey = EVP_PKEY_new();
+
+ ret = ctx->pmeth->paramgen(ctx, *ppkey);
+ if (ret <= 0)
+ {
+ EVP_PKEY_free(*ppkey);
+ *ppkey = NULL;
+ }
+ return ret;
+ }
+
+int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
+ {
+ int ret;
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen)
+ {
+ EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ ctx->operation = EVP_PKEY_OP_KEYGEN;
+ if (!ctx->pmeth->keygen_init)
+ return 1;
+ ret = ctx->pmeth->keygen_init(ctx);
+ if (ret <= 0)
+ ctx->operation = EVP_PKEY_OP_UNDEFINED;
+ return ret;
+ }
+
+int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+ {
+ int ret;
+
+ if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen)
+ {
+ EVPerr(EVP_F_EVP_PKEY_KEYGEN,
+ EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ return -2;
+ }
+ if (ctx->operation != EVP_PKEY_OP_KEYGEN)
+ {
+ EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED);
+ return -1;
+ }
+
+ if (!ppkey)
+ return -1;
+
+ if (!*ppkey)
+ *ppkey = EVP_PKEY_new();
+
+ ret = ctx->pmeth->keygen(ctx, *ppkey);
+ if (ret <= 0)
+ {
+ EVP_PKEY_free(*ppkey);
+ *ppkey = NULL;
+ }
+ return ret;
+ }
+
+void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
+ {
+ ctx->pkey_gencb = cb;
+ }
+
+/* "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB
+ * style callbacks.
+ */
+
+static int trans_cb(int a, int b, BN_GENCB *gcb)
+ {
+ EVP_PKEY_CTX *ctx = gcb->arg;
+ ctx->keygen_info[0] = a;
+ ctx->keygen_info[1] = b;
+ return ctx->pkey_gencb(ctx);
+ }
+
+void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
+ {
+ BN_GENCB_set(cb, trans_cb, ctx)
+ }
+
+int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
+ {
+ if (idx == -1)
+ return ctx->keygen_info_count;
+ if (idx < 0 || idx > ctx->keygen_info_count)
+ return 0;
+ return ctx->keygen_info[idx];
+ }
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 26a55048ca..3c8d0a6e4f 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -101,20 +101,25 @@ const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type, ENGINE *e)
return *ret;
}
-EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey)
+static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
{
EVP_PKEY_CTX *ret;
const EVP_PKEY_METHOD *pmeth;
- if (!pkey || !pkey->ameth)
- return NULL;
- pmeth = EVP_PKEY_meth_find(pkey->ameth->pkey_id, NULL);
+ if (id == -1)
+ {
+ if (!pkey || !pkey->ameth)
+ return NULL;
+ id = pkey->ameth->pkey_id;
+ }
+ pmeth = EVP_PKEY_meth_find(id, e);
if (pmeth == NULL)
return NULL;
ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
- CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
ret->pkey = pkey;
+ if (pkey)
+ CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
ret->data = NULL;
if (pmeth->init)
@@ -129,6 +134,16 @@ EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey)
return ret;
}
+EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
+ {
+ return int_ctx_new(pkey, e, -1);
+ }
+
+EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
+ {
+ return int_ctx_new(NULL, e, id);
+ }
+
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
{
if (ctx->pmeth && ctx->pmeth->cleanup)
@@ -191,3 +206,23 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
}
return ctx->pmeth->ctrl_str(ctx, name, value);
}
+
+void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
+ {
+ ctx->data = data;
+ }
+
+void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
+ {
+ return ctx->data;
+ }
+
+void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
+ {
+ ctx->app_data = data;
+ }
+
+void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
+ {
+ return ctx->app_data;
+ }
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index 378bfe4b4e..56759b5285 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -75,6 +75,8 @@ typedef struct
/* Key gen parameters */
int nbits;
BIGNUM *pub_exp;
+ /* Keygen callback info */
+ int gentmp[2];
/* RSA padding mode */
int pad_mode;
/* message digest */
@@ -100,6 +102,8 @@ static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
rctx->saltlen = -2;
ctx->data = rctx;
+ ctx->keygen_info = rctx->gentmp;
+ ctx->keygen_info_count = 2;
return 1;
}
@@ -427,6 +431,36 @@ static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
return -2;
}
+static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+ {
+ RSA *rsa = NULL;
+ RSA_PKEY_CTX *rctx = ctx->data;
+ BN_GENCB *pcb, cb;
+ int ret;
+ if (!rctx->pub_exp)
+ {
+ rctx->pub_exp = BN_new();
+ if (!rctx->pub_exp || !BN_set_word(rctx->pub_exp, RSA_F4))
+ return 0;
+ }
+ rsa = RSA_new();
+ if (!rsa)
+ return 0;
+ if (ctx->pkey_gencb)
+ {
+ pcb = &cb;
+ evp_pkey_set_cb_translate(pcb, ctx);
+ }
+ else
+ pcb = NULL;
+ ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
+ if (ret > 0)
+ EVP_PKEY_assign_RSA(pkey, rsa);
+ else
+ RSA_free(rsa);
+ return ret;
+ }
+
const EVP_PKEY_METHOD rsa_pkey_meth =
{
EVP_PKEY_RSA,
@@ -436,7 +470,8 @@ const EVP_PKEY_METHOD rsa_pkey_meth =
0,0,
- 0,0,
+ 0,
+ pkey_rsa_keygen,
0,
pkey_rsa_sign,