Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 1 | /* |
Rich Salz | 6286757 | 2016-05-17 14:24:46 -0400 | [diff] [blame] | 2 | * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 3 | * |
Rich Salz | 6286757 | 2016-05-17 14:24:46 -0400 | [diff] [blame] | 4 | * Licensed under the OpenSSL license (the "License"). You may not use |
| 5 | * this file except in compliance with the License. You can obtain a copy |
| 6 | * in the file LICENSE in the source distribution or at |
| 7 | * https://www.openssl.org/source/license.html |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
| 10 | #include <stdio.h> |
| 11 | #include <stdlib.h> |
Richard Levitte | b39fc56 | 2015-05-14 16:56:48 +0200 | [diff] [blame] | 12 | #include "internal/cryptlib.h" |
Dr. Stephen Henson | c20276e | 2006-04-17 12:08:22 +0000 | [diff] [blame] | 13 | #include <openssl/objects.h> |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 14 | #include <openssl/evp.h> |
Matt Caswell | 68c29f6 | 2014-10-28 22:59:34 +0000 | [diff] [blame] | 15 | #include "internal/bn_int.h" |
Dr. Stephen Henson | 27af42f | 2015-03-23 22:57:47 +0000 | [diff] [blame] | 16 | #include "internal/evp_int.h" |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 17 | |
| 18 | int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 19 | { |
| 20 | int ret; |
| 21 | if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { |
| 22 | EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT, |
| 23 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); |
| 24 | return -2; |
| 25 | } |
| 26 | ctx->operation = EVP_PKEY_OP_PARAMGEN; |
| 27 | if (!ctx->pmeth->paramgen_init) |
| 28 | return 1; |
| 29 | ret = ctx->pmeth->paramgen_init(ctx); |
| 30 | if (ret <= 0) |
| 31 | ctx->operation = EVP_PKEY_OP_UNDEFINED; |
| 32 | return ret; |
| 33 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 34 | |
| 35 | int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 36 | { |
| 37 | int ret; |
| 38 | if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { |
| 39 | EVPerr(EVP_F_EVP_PKEY_PARAMGEN, |
| 40 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); |
| 41 | return -2; |
| 42 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 43 | |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 44 | if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { |
| 45 | EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED); |
| 46 | return -1; |
| 47 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 48 | |
Emilia Kasper | e34c66c | 2015-09-01 16:31:55 +0200 | [diff] [blame] | 49 | if (ppkey == NULL) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 50 | return -1; |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 51 | |
Emilia Kasper | e34c66c | 2015-09-01 16:31:55 +0200 | [diff] [blame] | 52 | if (*ppkey == NULL) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 53 | *ppkey = EVP_PKEY_new(); |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 54 | |
Emilia Kasper | e34c66c | 2015-09-01 16:31:55 +0200 | [diff] [blame] | 55 | if (*ppkey == NULL) { |
| 56 | EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE); |
| 57 | return -1; |
| 58 | } |
| 59 | |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 60 | ret = ctx->pmeth->paramgen(ctx, *ppkey); |
| 61 | if (ret <= 0) { |
| 62 | EVP_PKEY_free(*ppkey); |
| 63 | *ppkey = NULL; |
| 64 | } |
| 65 | return ret; |
| 66 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 67 | |
| 68 | int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 69 | { |
| 70 | int ret; |
| 71 | if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { |
| 72 | EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT, |
| 73 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); |
| 74 | return -2; |
| 75 | } |
| 76 | ctx->operation = EVP_PKEY_OP_KEYGEN; |
| 77 | if (!ctx->pmeth->keygen_init) |
| 78 | return 1; |
| 79 | ret = ctx->pmeth->keygen_init(ctx); |
| 80 | if (ret <= 0) |
| 81 | ctx->operation = EVP_PKEY_OP_UNDEFINED; |
| 82 | return ret; |
| 83 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 84 | |
| 85 | int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 86 | { |
| 87 | int ret; |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 88 | |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 89 | if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { |
| 90 | EVPerr(EVP_F_EVP_PKEY_KEYGEN, |
| 91 | EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); |
| 92 | return -2; |
| 93 | } |
| 94 | if (ctx->operation != EVP_PKEY_OP_KEYGEN) { |
| 95 | EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED); |
| 96 | return -1; |
| 97 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 98 | |
Matt Caswell | 90945fa | 2015-10-30 11:12:26 +0000 | [diff] [blame] | 99 | if (ppkey == NULL) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 100 | return -1; |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 101 | |
Matt Caswell | 90945fa | 2015-10-30 11:12:26 +0000 | [diff] [blame] | 102 | if (*ppkey == NULL) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 103 | *ppkey = EVP_PKEY_new(); |
Matt Caswell | 90945fa | 2015-10-30 11:12:26 +0000 | [diff] [blame] | 104 | if (*ppkey == NULL) |
| 105 | return -1; |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 106 | |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 107 | ret = ctx->pmeth->keygen(ctx, *ppkey); |
| 108 | if (ret <= 0) { |
| 109 | EVP_PKEY_free(*ppkey); |
| 110 | *ppkey = NULL; |
| 111 | } |
| 112 | return ret; |
| 113 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 114 | |
| 115 | void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 116 | { |
| 117 | ctx->pkey_gencb = cb; |
| 118 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 119 | |
Dr. Stephen Henson | b28dea4 | 2006-05-31 17:34:14 +0000 | [diff] [blame] | 120 | EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 121 | { |
| 122 | return ctx->pkey_gencb; |
| 123 | } |
Dr. Stephen Henson | b28dea4 | 2006-05-31 17:34:14 +0000 | [diff] [blame] | 124 | |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 125 | /* |
| 126 | * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style |
| 127 | * callbacks. |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 128 | */ |
| 129 | |
| 130 | static int trans_cb(int a, int b, BN_GENCB *gcb) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 131 | { |
| 132 | EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb); |
| 133 | ctx->keygen_info[0] = a; |
| 134 | ctx->keygen_info[1] = b; |
| 135 | return ctx->pkey_gencb(ctx); |
| 136 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 137 | |
| 138 | void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 139 | { |
| 140 | BN_GENCB_set(cb, trans_cb, ctx); |
| 141 | } |
Dr. Stephen Henson | f5cda4c | 2006-04-11 13:28:52 +0000 | [diff] [blame] | 142 | |
| 143 | int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 144 | { |
| 145 | if (idx == -1) |
| 146 | return ctx->keygen_info_count; |
| 147 | if (idx < 0 || idx > ctx->keygen_info_count) |
| 148 | return 0; |
| 149 | return ctx->keygen_info[idx]; |
| 150 | } |
Dr. Stephen Henson | 2022cfe | 2007-04-11 17:20:40 +0000 | [diff] [blame] | 151 | |
| 152 | EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 153 | const unsigned char *key, int keylen) |
| 154 | { |
| 155 | EVP_PKEY_CTX *mac_ctx = NULL; |
| 156 | EVP_PKEY *mac_key = NULL; |
| 157 | mac_ctx = EVP_PKEY_CTX_new_id(type, e); |
| 158 | if (!mac_ctx) |
| 159 | return NULL; |
| 160 | if (EVP_PKEY_keygen_init(mac_ctx) <= 0) |
| 161 | goto merr; |
Dr. Stephen Henson | eff1a4d | 2015-02-10 18:06:56 +0000 | [diff] [blame] | 162 | if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0) |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 163 | goto merr; |
| 164 | if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0) |
| 165 | goto merr; |
| 166 | merr: |
Rich Salz | c5ba2d9 | 2015-03-28 10:54:15 -0400 | [diff] [blame] | 167 | EVP_PKEY_CTX_free(mac_ctx); |
Matt Caswell | 0f113f3 | 2015-01-22 03:40:55 +0000 | [diff] [blame] | 168 | return mac_key; |
| 169 | } |