Latest update.

This commit is contained in:
2020-04-15 18:45:34 +09:00
parent be29e7bcc6
commit 2015c00c43
573 changed files with 22943 additions and 6714 deletions
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -145,6 +145,7 @@ static ASN1_ITEM_EXP *asn1_item_list[] = {
#endif
ASN1_ITEM_ref(SXNETID),
ASN1_ITEM_ref(SXNET),
ASN1_ITEM_ref(ISSUER_SIGN_TOOL),
ASN1_ITEM_ref(USERNOTICE),
ASN1_ITEM_ref(X509_ALGORS),
ASN1_ITEM_ref(X509_ALGOR),
+88 -30
View File
@@ -22,11 +22,13 @@ static int _asn1_check_infinite_end(const unsigned char **p, long len)
/*
* If there is 0 or 1 byte left, the length check should pick things up
*/
if (len <= 0)
return 1;
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
(*p) += 2;
if (len <= 0) {
return 1;
} else {
if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
(*p) += 2;
return 1;
}
}
return 0;
}
@@ -45,7 +47,7 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
int *pclass, long omax)
{
int i, ret;
long l;
long len;
const unsigned char *p = *pp;
int tag, xclass, inf;
long max = omax;
@@ -59,18 +61,18 @@ int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
p++;
if (--max == 0)
goto err;
l = 0;
len = 0;
while (*p & 0x80) {
l <<= 7L;
l |= *(p++) & 0x7f;
len <<= 7L;
len |= *(p++) & 0x7f;
if (--max == 0)
goto err;
if (l > (INT_MAX >> 7L))
if (len > (INT_MAX >> 7L))
goto err;
}
l <<= 7L;
l |= *(p++) & 0x7f;
tag = (int)l;
len <<= 7L;
len |= *(p++) & 0x7f;
tag = (int)len;
if (--max == 0)
goto err;
} else {
@@ -141,8 +143,9 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
}
if (ret > LONG_MAX)
return 0;
} else
} else {
ret = i;
}
}
*pp = p;
*rl = (long)ret;
@@ -160,9 +163,9 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
i |= (xclass & V_ASN1_PRIVATE);
if (tag < 31)
if (tag < 31) {
*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
else {
} else {
*(p++) = i | V_ASN1_PRIMITIVE_TAG;
for (i = 0, ttag = tag; ttag > 0; i++)
ttag >>= 7;
@@ -185,6 +188,7 @@ void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
int ASN1_put_eoc(unsigned char **pp)
{
unsigned char *p = *pp;
*p++ = 0;
*p++ = 0;
*pp = p;
@@ -194,20 +198,21 @@ int ASN1_put_eoc(unsigned char **pp)
static void asn1_put_length(unsigned char **pp, int length)
{
unsigned char *p = *pp;
int i, l;
if (length <= 127)
int i, len;
if (length <= 127) {
*(p++) = (unsigned char)length;
else {
l = length;
for (i = 0; l > 0; i++)
l >>= 8;
} else {
len = length;
for (i = 0; len > 0; i++)
len >>= 8;
*(p++) = i | 0x80;
l = i;
len = i;
while (i-- > 0) {
p[i] = length & 0xff;
length >>= 8;
}
p += l;
p += len;
}
*pp = p;
}
@@ -215,6 +220,7 @@ static void asn1_put_length(unsigned char **pp, int length)
int ASN1_object_size(int constructed, int length, int tag)
{
int ret = 1;
if (length < 0)
return -1;
if (tag >= 31) {
@@ -256,6 +262,7 @@ int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
{
ASN1_STRING *ret;
if (!str)
return NULL;
ret = ASN1_STRING_new();
@@ -268,18 +275,29 @@ ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
return ret;
}
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len_in)
{
unsigned char *c;
const char *data = _data;
size_t len;
if (len < 0) {
if (len_in < 0) {
if (data == NULL)
return 0;
else
len = strlen(data);
len = strlen(data);
} else {
len = (size_t)len_in;
}
if ((str->length <= len) || (str->data == NULL)) {
/*
* Verify that the length fits within an integer for assignment to
* str->length below. The additional 1 is subtracted to allow for the
* '\0' terminator even though this isn't strictly necessary.
*/
if (len > INT_MAX - 1) {
ASN1err(0, ASN1_R_TOO_LARGE);
return 0;
}
if ((size_t)str->length <= len || str->data == NULL) {
c = str->data;
str->data = OPENSSL_realloc(c, len + 1);
if (str->data == NULL) {
@@ -359,8 +377,9 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
return a->type - b->type;
else
return i;
} else
} else {
return i;
}
}
int ASN1_STRING_length(const ASN1_STRING *x)
@@ -383,9 +402,48 @@ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
return x->data;
}
# ifndef OPENSSL_NO_DEPRECATED_1_1_0
#ifndef OPENSSL_NO_DEPRECATED_1_1_0
unsigned char *ASN1_STRING_data(ASN1_STRING *x)
{
return x->data;
}
#endif
char *sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, const char *sep,
size_t max_len /* excluding NUL terminator */)
{
int i;
ASN1_UTF8STRING *current;
size_t length = 0, sep_len;
char *result = NULL;
char *p;
if (!ossl_assert(sep != NULL))
return NULL;
sep_len = strlen(sep);
for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) {
current = sk_ASN1_UTF8STRING_value(text, i);
if (i > 0)
length += sep_len;
length += ASN1_STRING_length(current);
if (length > max_len)
return NULL;
}
if ((result = OPENSSL_malloc(length + 1)) == NULL)
return NULL;
for (i = 0, p = result; i < sk_ASN1_UTF8STRING_num(text); ++i) {
current = sk_ASN1_UTF8STRING_value(text, i);
length = ASN1_STRING_length(current);
if (i > 0 && sep_len > 0) {
strncpy(p, sep, sep_len + 1);
p += sep_len;
}
strncpy(p, (const char *)ASN1_STRING_get0_data(current), length);
p += length;
}
*p = '\0';
return result;
}
+9 -1
View File
@@ -11,7 +11,15 @@ IF[{- !$disabled{asm} -}]
ENDIF
ENDIF
SOURCE[../../libcrypto]=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM
$ALL=bf_skey.c bf_ecb.c bf_cfb64.c bf_ofb64.c $BFASM
SOURCE[../../libcrypto]=$ALL
# When all deprecated symbols are removed, libcrypto doesn't export the
# blowfish functions, so we must include them directly in liblegacy.a
IF[{- $disabled{'deprecated-3.0'} -}]
SOURCE[../../providers/liblegacy.a]=$ALL
ENDIF
GENERATE[bf-586.s]=asm/bf-586.pl
DEPEND[bf-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+12
View File
@@ -12,6 +12,7 @@
#include <errno.h>
#include "bio_local.h"
#include "internal/ktls.h"
#include <openssl/err.h>
@@ -51,6 +52,17 @@ int BIO_socket(int domain, int socktype, int protocol, int options)
BIOerr(BIO_F_BIO_SOCKET, BIO_R_UNABLE_TO_CREATE_SOCKET);
return INVALID_SOCKET;
}
# ifndef OPENSSL_NO_KTLS
{
/*
* The new socket is created successfully regardless of ktls_enable.
* ktls_enable doesn't change any functionality of the socket, except
* changing the setsockopt to enable the processing of ktls_start.
* Thus, it is not a problem to call it for non-TLS sockets.
*/
ktls_enable(sock);
}
# endif
return sock;
}
+1 -1
View File
@@ -750,7 +750,7 @@ int BIO_set_ex_data(BIO *bio, int idx, void *data)
return CRYPTO_set_ex_data(&(bio->ex_data), idx, data);
}
void *BIO_get_ex_data(BIO *bio, int idx)
void *BIO_get_ex_data(const BIO *bio, int idx)
{
return CRYPTO_get_ex_data(&(bio->ex_data), idx);
}
+7 -6
View File
@@ -222,19 +222,20 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
break;
case ACPT_S_CREATE_SOCKET:
ret = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
BIO_ADDRINFO_socktype(c->addr_iter),
BIO_ADDRINFO_protocol(c->addr_iter), 0);
if (ret == (int)INVALID_SOCKET) {
s = BIO_socket(BIO_ADDRINFO_family(c->addr_iter),
BIO_ADDRINFO_socktype(c->addr_iter),
BIO_ADDRINFO_protocol(c->addr_iter), 0);
if (s == (int)INVALID_SOCKET) {
ERR_raise_data(ERR_LIB_SYS, get_last_socket_error(),
"calling socket(%s, %s)",
c->param_addr, c->param_serv);
BIOerr(BIO_F_ACPT_STATE, BIO_R_UNABLE_TO_CREATE_SOCKET);
goto exit_loop;
}
c->accept_sock = ret;
b->num = ret;
c->accept_sock = s;
b->num = s;
c->state = ACPT_S_LISTEN;
s = -1;
break;
case ACPT_S_LISTEN:
+52 -2
View File
@@ -11,6 +11,7 @@
#include <errno.h>
#include "bio_local.h"
#include "internal/ktls.h"
#ifndef OPENSSL_NO_SOCK
@@ -20,6 +21,9 @@ typedef struct bio_connect_st {
char *param_hostname;
char *param_service;
int connect_mode;
# ifndef OPENSSL_NO_KTLS
unsigned char record_type;
# endif
BIO_ADDRINFO *addr_first;
const BIO_ADDRINFO *addr_iter;
@@ -308,7 +312,12 @@ static int conn_read(BIO *b, char *out, int outl)
if (out != NULL) {
clear_socket_error();
ret = readsocket(b->num, out, outl);
# ifndef OPENSSL_NO_KTLS
if (BIO_get_ktls_recv(b))
ret = ktls_read_record(b->num, out, outl);
else
# endif
ret = readsocket(b->num, out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -333,7 +342,16 @@ static int conn_write(BIO *b, const char *in, int inl)
}
clear_socket_error();
ret = writesocket(b->num, in, inl);
# ifndef OPENSSL_NO_KTLS
if (BIO_should_ktls_ctrl_msg_flag(b)) {
ret = ktls_send_ctrl_message(b->num, data->record_type, in, inl);
if (ret >= 0) {
ret = inl;
BIO_clear_ktls_ctrl_msg_flag(b);
}
} else
# endif
ret = writesocket(b->num, in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_sock_should_retry(ret))
@@ -349,6 +367,13 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
const char **pptr = NULL;
long ret = 1;
BIO_CONNECT *data;
# ifndef OPENSSL_NO_KTLS
# ifdef __FreeBSD__
struct tls_enable *crypto_info;
# else
struct tls12_crypto_info_aes_gcm_128 *crypto_info;
# endif
# endif
data = (BIO_CONNECT *)b->ptr;
@@ -497,6 +522,31 @@ static long conn_ctrl(BIO *b, int cmd, long num, void *ptr)
case BIO_CTRL_EOF:
ret = (b->flags & BIO_FLAGS_IN_EOF) != 0 ? 1 : 0;
break;
# ifndef OPENSSL_NO_KTLS
case BIO_CTRL_SET_KTLS:
# ifdef __FreeBSD__
crypto_info = (struct tls_enable *)ptr;
# else
crypto_info = (struct tls12_crypto_info_aes_gcm_128 *)ptr;
# endif
ret = ktls_start(b->num, crypto_info, sizeof(*crypto_info), num);
if (ret)
BIO_set_ktls_flag(b, num);
break;
case BIO_CTRL_GET_KTLS_SEND:
return BIO_should_ktls_flag(b, 1);
case BIO_CTRL_GET_KTLS_RECV:
return BIO_should_ktls_flag(b, 0);
case BIO_CTRL_SET_KTLS_TX_SEND_CTRL_MSG:
BIO_set_ktls_ctrl_msg_flag(b);
data->record_type = num;
ret = 0;
break;
case BIO_CTRL_CLEAR_KTLS_TX_CTRL_MSG:
BIO_clear_ktls_ctrl_msg_flag(b);
ret = 0;
break;
# endif
default:
ret = 0;
break;
+4 -1
View File
@@ -70,7 +70,8 @@ SOURCE[../providers/libfips.a]=$CORE_COMMON
$UTIL_COMMON=\
cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
ctype.c threads_pthread.c threads_win.c threads_none.c initthread.c \
context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM
context.c sparse_array.c asn1_dsa.c packet.c param_build.c $CPUIDASM \
param_build_set.c der_writer.c
$UTIL_DEFINE=$CPUIDDEF
SOURCE[../libcrypto]=$UTIL_COMMON \
@@ -79,6 +80,7 @@ SOURCE[../libcrypto]=$UTIL_COMMON \
o_fopen.c getenv.c o_init.c o_fips.c init.c trace.c provider.c \
$UPLINKSRC
SOURCE[../providers/libfips.a]=$UTIL_COMMON
SOURCE[../providers/liblegacy.a]=$UTIL_COMMON
# Implementations are now spread across several libraries, so the defines
# need to be applied to all affected libraries and modules.
@@ -86,6 +88,7 @@ DEFINE[../libcrypto]=$UTIL_DEFINE $UPLINKDEF
DEFINE[../providers/libfips.a]=$UTIL_DEFINE
DEFINE[../providers/fips]=$UTIL_DEFINE
DEFINE[../providers/libimplementations.a]=$UTIL_DEFINE
DEFINE[../providers/liblegacy.a]=$UTIL_DEFINE
DEFINE[../providers/libcommon.a]=$UTIL_DEFINE
DEPEND[info.o]=buildinf.h
+9 -1
View File
@@ -12,7 +12,15 @@ IF[{- !$disabled{asm} && !$disabled{pic} -}]
ENDIF
ENDIF
SOURCE[../../libcrypto]=c_skey.c c_ecb.c $CASTASM c_cfb64.c c_ofb64.c
$ALL=c_skey.c c_ecb.c $CASTASM c_cfb64.c c_ofb64.c
SOURCE[../../libcrypto]=$ALL
# When all deprecated symbols are removed, libcrypto doesn't export the
# cast functions, so we must include them directly in liblegacy.a
IF[{- $disabled{'deprecated-3.0'} -}]
SOURCE[../../providers/liblegacy.a]=$ALL
ENDIF
GENERATE[cast-586.s]=asm/cast-586.pl
DEPEND[cast-586.s]=../perlasm/x86asm.pl ../perlasm/cbc.pl
+2 -1
View File
@@ -1,3 +1,4 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]= cmp_asn.c cmp_ctx.c cmp_err.c cmp_util.c \
cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c
cmp_status.c cmp_hdr.c cmp_protect.c cmp_msg.c cmp_vfy.c \
cmp_server.c cmp_client.c cmp_http.c
+881
View File
@@ -0,0 +1,881 @@
/*
* Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "cmp_local.h"
#include "internal/cryptlib.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/bio.h>
#include <openssl/cmp.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include "openssl/cmp_util.h"
#define IS_CREP(t) ((t) == OSSL_CMP_PKIBODY_IP || (t) == OSSL_CMP_PKIBODY_CP \
|| (t) == OSSL_CMP_PKIBODY_KUP)
/*-
* Evaluate whether there's an exception (violating the standard) configured for
* handling negative responses without protection or with invalid protection.
* Returns 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *rep,
int invalid_protection,
int expected_type /* ignored here */)
{
int rcvd_type = ossl_cmp_msg_get_bodytype(rep /* may be NULL */);
const char *msg_type = NULL;
if (!ossl_assert(ctx != NULL && rep != NULL))
return -1;
if (!ctx->unprotectedErrors)
return 0;
switch (rcvd_type) {
case OSSL_CMP_PKIBODY_ERROR:
msg_type = "error response";
break;
case OSSL_CMP_PKIBODY_RP:
{
OSSL_CMP_PKISI *si =
ossl_cmp_revrepcontent_get_pkisi(rep->body->value.rp,
OSSL_CMP_REVREQSID);
if (si == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_rejection)
msg_type = "revocation response message with rejection status";
break;
}
case OSSL_CMP_PKIBODY_PKICONF:
msg_type = "PKI Confirmation message";
break;
default:
if (IS_CREP(rcvd_type)) {
OSSL_CMP_CERTREPMESSAGE *crepmsg = rep->body->value.ip;
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(crepmsg,
-1 /* any rid */);
if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1)
return -1;
/* TODO: handle potentially multiple CertResponses in CertRepMsg */
if (crep == NULL)
return -1;
if (ossl_cmp_pkisi_get_status(crep->status)
== OSSL_CMP_PKISTATUS_rejection)
msg_type = "CertRepMessage with rejection status";
}
}
if (msg_type == NULL)
return 0;
ossl_cmp_log2(WARN, ctx, "ignoring %s protection of %s",
invalid_protection ? "invalid" : "missing", msg_type);
return 1;
}
/* Save error info from PKIStatusInfo field of a certresponse into ctx */
static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si)
{
int i;
OSSL_CMP_PKIFREETEXT *ss;
if (!ossl_assert(ctx != NULL && si != NULL))
return 0;
if ((ctx->status = ossl_cmp_pkisi_get_status(si)) < 0)
return 0;
ctx->failInfoCode = 0;
if (si->failInfo != NULL) {
for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++) {
if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
ctx->failInfoCode |= (1 << i);
}
}
if (!ossl_cmp_ctx_set0_statusString(ctx, sk_ASN1_UTF8STRING_new_null())
|| (ctx->statusString == NULL))
return 0;
ss = si->statusString; /* may be NULL */
for (i = 0; i < sk_ASN1_UTF8STRING_num(ss); i++) {
ASN1_UTF8STRING *str = sk_ASN1_UTF8STRING_value(ss, i);
if (!sk_ASN1_UTF8STRING_push(ctx->statusString, ASN1_STRING_dup(str)))
return 0;
}
return 1;
}
/*-
* Perform the generic aspects of sending a request and receiving a response.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* Returns 0 on error.
* Regardless of success, caller is responsible for freeing *rep (unless NULL).
*/
static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req,
OSSL_CMP_MSG **rep, int expected_type)
{
const char *req_type_str =
ossl_cmp_bodytype_to_string(ossl_cmp_msg_get_bodytype(req));
const char *expected_type_str = ossl_cmp_bodytype_to_string(expected_type);
int msg_timeout;
int bt;
time_t now = time(NULL);
int time_left;
OSSL_CMP_transfer_cb_t transfer_cb = ctx->transfer_cb;
if (transfer_cb == NULL)
transfer_cb = OSSL_CMP_MSG_http_perform;
*rep = NULL;
msg_timeout = ctx->msg_timeout; /* backup original value */
if ((IS_CREP(expected_type) || expected_type == OSSL_CMP_PKIBODY_POLLREP)
&& ctx->total_timeout > 0 /* timeout is not infinite */) {
if (now >= ctx->end_time) {
CMPerr(0, CMP_R_TOTAL_TIMEOUT);
return 0;
}
if (!ossl_assert(ctx->end_time - time(NULL) < INT_MAX)) {
/* cannot really happen due to the assignment in do_certreq_seq() */
CMPerr(0, CMP_R_INVALID_ARGS);
return 0;
}
time_left = (int)(ctx->end_time - now);
if (ctx->msg_timeout == 0 || time_left < ctx->msg_timeout)
ctx->msg_timeout = time_left;
}
/* should print error queue since transfer_cb may call ERR_clear_error() */
OSSL_CMP_CTX_print_errors(ctx);
ossl_cmp_log1(INFO, ctx, "sending %s", req_type_str);
*rep = (*transfer_cb)(ctx, req);
ctx->msg_timeout = msg_timeout; /* restore original value */
if (*rep == NULL) {
CMPerr(0, CMP_R_TRANSFER_ERROR); /* or receiving response */
ERR_add_error_data(1, req_type_str);
ERR_add_error_data(2, ", expected response: ", expected_type_str);
return 0;
}
bt = ossl_cmp_msg_get_bodytype(*rep);
/*
* The body type in the 'bt' variable is not yet verified.
* Still we use this preliminary value already for a progress report because
* the following msg verification may also produce log entries and may fail.
*/
ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt));
if ((bt = ossl_cmp_msg_check_received(ctx, *rep, unprotected_exception,
expected_type)) < 0)
return 0;
if (bt == expected_type
/* as an answer to polling, there could be IP/CP/KUP: */
|| (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP))
return 1;
/* received message type is not one of the expected ones (e.g., error) */
CMPerr(0, bt == OSSL_CMP_PKIBODY_ERROR ? CMP_R_RECEIVED_ERROR :
CMP_R_UNEXPECTED_PKIBODY); /* in next line for mkerr.pl */
if (bt != OSSL_CMP_PKIBODY_ERROR) {
ERR_add_error_data(3, "message type is '",
ossl_cmp_bodytype_to_string(bt), "'");
} else {
OSSL_CMP_ERRORMSGCONTENT *emc = (*rep)->body->value.error;
OSSL_CMP_PKISI *si = emc->pKIStatusInfo;
char buf[OSSL_CMP_PKISI_BUFLEN];
if (save_statusInfo(ctx, si)
&& OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
if (emc->errorCode != NULL
&& BIO_snprintf(buf, sizeof(buf), "; errorCode: %ld",
ASN1_INTEGER_get(emc->errorCode)) > 0)
ERR_add_error_data(1, buf);
if (emc->errorDetails != NULL) {
char *text = sk_ASN1_UTF8STRING2text(emc->errorDetails, ", ",
OSSL_CMP_PKISI_BUFLEN - 1);
if (text != NULL)
ERR_add_error_data(2, "; errorDetails: ", text);
OPENSSL_free(text);
}
if (ctx->status != OSSL_CMP_PKISTATUS_rejection) {
CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS);
if (ctx->status == OSSL_CMP_PKISTATUS_waiting)
ctx->status = OSSL_CMP_PKISTATUS_rejection;
}
}
return 0;
}
/*-
* When a 'waiting' PKIStatus has been received, this function is used to
* poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup.
* On receiving a pollRep, which includes a checkAfter value, it return this
* value if sleep == 0, else it sleeps as long as indicated and retries.
*
* A transaction timeout is enabled if ctx->total_timeout is > 0.
* In this case polling will continue until the timeout is reached and then
* polling is done a last time even if this is before the "checkAfter" time.
*
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *rep.
* In this case the caller is responsible for freeing *rep.
* Returns 0 on error (which includes the case that timeout has been reached).
*/
static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **rep, int *checkAfter)
{
OSSL_CMP_MSG *preq = NULL;
OSSL_CMP_MSG *prep = NULL;
ossl_cmp_info(ctx,
"received 'waiting' PKIStatus, starting to poll for response");
*rep = NULL;
for (;;) {
/* TODO: handle potentially multiple poll requests per message */
if ((preq = ossl_cmp_pollReq_new(ctx, rid)) == NULL)
goto err;
if (!send_receive_check(ctx, preq, &prep, OSSL_CMP_PKIBODY_POLLREP))
goto err;
/* handle potential pollRep */
if (ossl_cmp_msg_get_bodytype(prep) == OSSL_CMP_PKIBODY_POLLREP) {
OSSL_CMP_POLLREPCONTENT *prc = prep->body->value.pollRep;
OSSL_CMP_POLLREP *pollRep = NULL;
int64_t check_after;
char str[OSSL_CMP_PKISI_BUFLEN];
int len;
/* TODO: handle potentially multiple elements in pollRep */
if (sk_OSSL_CMP_POLLREP_num(prc) > 1) {
CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
goto err;
}
pollRep = ossl_cmp_pollrepcontent_get0_pollrep(prc, rid);
if (pollRep == NULL)
goto err;
if (!ASN1_INTEGER_get_int64(&check_after, pollRep->checkAfter)) {
CMPerr(0, CMP_R_BAD_CHECKAFTER_IN_POLLREP);
goto err;
}
if (check_after < 0 || (uint64_t)check_after
> (sleep ? ULONG_MAX / 1000 : INT_MAX)) {
CMPerr(0, CMP_R_CHECKAFTER_OUT_OF_RANGE);
if (BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN, "value = %jd",
check_after) >= 0)
ERR_add_error_data(1, str);
goto err;
}
if (ctx->total_timeout > 0) { /* timeout is not infinite */
const int exp = 5; /* expected max time per msg round trip */
int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL));
if (time_left <= 0) {
CMPerr(0, CMP_R_TOTAL_TIMEOUT);
goto err;
}
if (time_left < check_after)
check_after = time_left;
/* poll one last time just when timeout was reached */
}
if (pollRep->reason == NULL
|| (len = BIO_snprintf(str, OSSL_CMP_PKISI_BUFLEN,
" with reason = '")) < 0) {
*str = '\0';
} else {
char *text = sk_ASN1_UTF8STRING2text(pollRep->reason, ", ",
sizeof(str) - len - 2);
if (text == NULL
|| BIO_snprintf(str + len, sizeof(str) - len,
"%s'", text) < 0)
*str = '\0';
OPENSSL_free(text);
}
ossl_cmp_log2(INFO, ctx,
"received polling response%s; checkAfter = %ld seconds",
str, check_after);
OSSL_CMP_MSG_free(preq);
preq = NULL;
OSSL_CMP_MSG_free(prep);
prep = NULL;
if (sleep) {
ossl_sleep((unsigned long)(1000 * check_after));
} else {
if (checkAfter != NULL)
*checkAfter = (int)check_after;
return -1; /* exits the loop */
}
} else {
ossl_cmp_info(ctx, "received ip/cp/kup after polling");
/* any other body type has been rejected by send_receive_check() */
break;
}
}
if (prep == NULL)
goto err;
OSSL_CMP_MSG_free(preq);
*rep = prep;
return 1;
err:
OSSL_CMP_MSG_free(preq);
OSSL_CMP_MSG_free(prep);
return 0;
}
/* Send certConf for IR, CR or KUR sequences and check response */
int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
const char *txt)
{
OSSL_CMP_MSG *certConf;
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
/* OSSL_CMP_certConf_new() also checks if all necessary options are set */
if ((certConf = ossl_cmp_certConf_new(ctx, fail_info, txt)) == NULL)
goto err;
res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(certConf);
OSSL_CMP_MSG_free(PKIconf);
return res;
}
/* Send given error and check response */
int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
const char *txt, int errorCode, const char *details)
{
OSSL_CMP_MSG *error = NULL;
OSSL_CMP_PKISI *si = NULL;
OSSL_CMP_MSG *PKIconf = NULL;
int res = 0;
if ((si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt)) == NULL)
goto err;
/* ossl_cmp_error_new() also checks if all necessary options are set */
if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL)
goto err;
res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF);
err:
OSSL_CMP_MSG_free(error);
OSSL_CMP_PKISI_free(si);
OSSL_CMP_MSG_free(PKIconf);
return res;
}
/*-
* Retrieve a copy of the certificate, if any, from the given CertResponse.
* Take into account PKIStatusInfo of CertResponse in ctx, report it on error.
* Returns NULL if not found or on error.
*/
static X509 *get1_cert_status(OSSL_CMP_CTX *ctx, int bodytype,
OSSL_CMP_CERTRESPONSE *crep)
{
char buf[OSSL_CMP_PKISI_BUFLEN];
X509 *crt = NULL;
EVP_PKEY *privkey;
if (!ossl_assert(ctx != NULL && crep != NULL))
return NULL;
privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
switch (ossl_cmp_pkisi_get_status(crep->status)) {
case OSSL_CMP_PKISTATUS_waiting:
ossl_cmp_err(ctx,
"received \"waiting\" status for cert when actually aiming to extract cert");
CMPerr(0, CMP_R_ENCOUNTERED_WAITING);
goto err;
case OSSL_CMP_PKISTATUS_grantedWithMods:
ossl_cmp_warn(ctx, "received \"grantedWithMods\" for certificate");
crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
break;
case OSSL_CMP_PKISTATUS_accepted:
crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
break;
/* get all information in case of a rejection before going to error */
case OSSL_CMP_PKISTATUS_rejection:
ossl_cmp_err(ctx, "received \"rejection\" status rather than cert");
CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER);
goto err;
case OSSL_CMP_PKISTATUS_revocationWarning:
ossl_cmp_warn(ctx,
"received \"revocationWarning\" - a revocation of the cert is imminent");
crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
break;
case OSSL_CMP_PKISTATUS_revocationNotification:
ossl_cmp_warn(ctx,
"received \"revocationNotification\" - a revocation of the cert has occurred");
crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
break;
case OSSL_CMP_PKISTATUS_keyUpdateWarning:
if (bodytype != OSSL_CMP_PKIBODY_KUR) {
CMPerr(0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING);
goto err;
}
crt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
break;
default:
ossl_cmp_log1(ERROR, ctx,
"received unsupported PKIStatus %d for certificate",
ctx->status);
CMPerr(0, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
if (crt == NULL) /* according to PKIStatus, we can expect a cert */
CMPerr(0, CMP_R_CERTIFICATE_NOT_FOUND);
return crt;
err:
if (OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
return NULL;
}
/*-
* Callback fn validating that the new certificate can be verified, using
* ctx->certConf_cb_arg, which has been initialized using opt_out_trusted, and
* ctx->untrusted_certs, which at this point already contains ctx->extraCertsIn.
* Returns 0 on acceptance, else a bit field reflecting PKIFailureInfo.
* Quoting from RFC 4210 section 5.1. Overall PKI Message:
* The extraCerts field can contain certificates that may be useful to
* the recipient. For example, this can be used by a CA or RA to
* present an end entity with certificates that it needs to verify its
* own new certificate (if, for example, the CA that issued the end
* entity's certificate is not a root CA for the end entity). Note that
* this field does not necessarily contain a certification path; the
* recipient may have to sort, select from, or otherwise process the
* extra certificates in order to use them.
* Note: While often handy, there is no hard requirement by CMP that
* an EE must be able to validate the certificates it gets enrolled.
*/
int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info,
const char **text)
{
X509_STORE *out_trusted = OSSL_CMP_CTX_get_certConf_cb_arg(ctx);
(void)text; /* make (artificial) use of var to prevent compiler warning */
if (fail_info != 0) /* accept any error flagged by CMP core library */
return fail_info;
if (out_trusted != NULL
&& !OSSL_CMP_validate_cert_path(ctx, out_trusted, cert))
fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
return fail_info;
}
/*-
* Perform the generic handling of certificate responses for IR/CR/KUR/P10CR.
* Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value.
* Returns 1 on success and provides the received PKIMESSAGE in *resp.
* Returns 0 on error (which includes the case that timeout has been reached).
* Regardless of success, caller is responsible for freeing *resp (unless NULL).
*/
static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid,
OSSL_CMP_MSG **resp, int *checkAfter,
int req_type, int expected_type)
{
EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx /* may be NULL */, 0);
int fail_info = 0; /* no failure */
const char *txt = NULL;
OSSL_CMP_CERTREPMESSAGE *crepmsg;
OSSL_CMP_CERTRESPONSE *crep;
X509 *cert;
char *subj = NULL;
int ret = 1;
retry:
crepmsg = (*resp)->body->value.ip; /* same for cp and kup */
if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) {
CMPerr(0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED);
return 0;
}
/* TODO: handle potentially multiple CertResponses in CertRepMsg */
crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid);
if (crep == NULL)
return 0;
if (!save_statusInfo(ctx, crep->status))
return 0;
if (rid == -1) {
/* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */
rid = ossl_cmp_asn1_get_int(crep->certReqId);
if (rid == -1) {
CMPerr(0, CMP_R_BAD_REQUEST_ID);
return 0;
}
}
if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) {
OSSL_CMP_MSG_free(*resp);
*resp = NULL;
if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) {
if (ret == -1) /* at this point implies sleep == 0 */
return ret; /* waiting */
goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */
} else {
CMPerr(0, CMP_R_POLLING_FAILED);
return 0;
}
}
cert = get1_cert_status(ctx, (*resp)->body->type, crep);
if (cert == NULL) {
ERR_add_error_data(1, "; cannot extract certificate from response");
return 0;
}
if (!ossl_cmp_ctx_set0_newCert(ctx, cert))
return 0;
/*
* if the CMP server returned certificates in the caPubs field, copy them
* to the context so that they can be retrieved if necessary
*/
if (crepmsg->caPubs != NULL
&& !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs))
return 0;
/* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */
if (!ossl_cmp_ctx_set1_extraCertsIn(ctx, (*resp)->extraCerts))
return 0;
subj = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
if (rkey != NULL
/* X509_check_private_key() also works if rkey is just public key */
&& !(X509_check_private_key(ctx->newCert, rkey))) {
fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_incorrectData;
txt = "public key in new certificate does not match our enrollment key";
/*-
* not callling (void)ossl_cmp_exchange_error(ctx,
* OSSL_CMP_PKISTATUS_rejection, fail_info, txt)
* not throwing CMP_R_CERTIFICATE_NOT_ACCEPTED with txt
* not returning 0
* since we better leave this for any ctx->certConf_cb to decide
*/
}
/*
* Execute the certification checking callback function possibly set in ctx,
* which can determine whether to accept a newly enrolled certificate.
* It may overrule the pre-decision reflected in 'fail_info' and '*txt'.
*/
if (ctx->certConf_cb
&& (fail_info = ctx->certConf_cb(ctx, ctx->newCert,
fail_info, &txt)) != 0) {
if (txt == NULL)
txt = "CMP client application did not accept it";
}
if (fail_info != 0) /* immediately log error before any certConf exchange */
ossl_cmp_log1(ERROR, ctx,
"rejecting newly enrolled cert with subject: %s", subj);
/*
* TODO: better move certConf exchange to do_certreq_seq() such that
* also more low-level errors with CertReqMessages get reported to server
*/
if (!ctx->disableConfirm
&& !ossl_cmp_hdr_has_implicitConfirm((*resp)->header)) {
if (!ossl_cmp_exchange_certConf(ctx, fail_info, txt))
ret = 0;
}
/* not throwing failure earlier as transfer_cb may call ERR_clear_error() */
if (fail_info != 0) {
CMPerr(0, CMP_R_CERTIFICATE_NOT_ACCEPTED);
ERR_add_error_data(2, "rejecting newly enrolled cert with subject: ",
subj);
if (txt != NULL)
ERR_add_error_txt("; ", txt);
ret = 0;
}
OPENSSL_free(subj);
return ret;
}
int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, int *checkAfter)
{
OSSL_CMP_MSG *req = NULL;
OSSL_CMP_MSG *rep = NULL;
int is_p10 = req_type == OSSL_CMP_PKIBODY_P10CR;
int rid = is_p10 ? -1 : OSSL_CMP_CERTREQID;
int rep_type = is_p10 ? OSSL_CMP_PKIBODY_CP : req_type + 1;
int res = 0;
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */
ctx->status = -1;
if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
return 0;
if (ctx->total_timeout > 0) /* else ctx->end_time is not used */
ctx->end_time = time(NULL) + ctx->total_timeout;
req = ossl_cmp_certReq_new(ctx, req_type, 0 /* req_err */);
if (req == NULL) /* also checks if all necessary options are set */
return 0;
if (!send_receive_check(ctx, req, &rep, rep_type))
goto err;
} else {
if (req_type < 0)
return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection,
0 /* TODO better fail_info value? */,
"polling aborted", 0 /* errorCode */,
"by application");
res = poll_for_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter);
if (res <= 0) /* waiting or error */
return res;
}
res = cert_response(ctx, 0 /* no sleep */, rid, &rep, checkAfter,
req_type, rep_type);
err:
OSSL_CMP_MSG_free(req);
OSSL_CMP_MSG_free(rep);
return res;
}
/*-
* Do the full sequence CR/IR/KUR/P10CR, CP/IP/KUP/CP,
* certConf, PKIconf, and polling if required.
* Will sleep as long as indicated by the server (according to checkAfter).
* All enrollment options need to be present in the context.
* TODO: another function to request two certificates at once should be created.
* Returns pointer to received certificate, or NULL if none was received.
*/
static X509 *do_certreq_seq(OSSL_CMP_CTX *ctx, int req_type, int req_err,
int rep_type)
{
OSSL_CMP_MSG *req = NULL;
OSSL_CMP_MSG *rep = NULL;
int rid = (req_type == OSSL_CMP_PKIBODY_P10CR) ? -1 : OSSL_CMP_CERTREQID;
X509 *result = NULL;
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
ctx->status = -1;
if (!ossl_cmp_ctx_set0_newCert(ctx, NULL))
return NULL;
if (ctx->total_timeout > 0) /* else ctx->end_time is not used */
ctx->end_time = time(NULL) + ctx->total_timeout;
/* OSSL_CMP_certreq_new() also checks if all necessary options are set */
if ((req = ossl_cmp_certReq_new(ctx, req_type, req_err)) == NULL)
goto err;
if (!send_receive_check(ctx, req, &rep, rep_type))
goto err;
if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type)
<= 0)
goto err;
result = ctx->newCert;
err:
OSSL_CMP_MSG_free(req);
OSSL_CMP_MSG_free(rep);
return result;
}
X509 *OSSL_CMP_exec_IR_ses(OSSL_CMP_CTX *ctx)
{
return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_IR,
CMP_R_ERROR_CREATING_IR, OSSL_CMP_PKIBODY_IP);
}
X509 *OSSL_CMP_exec_CR_ses(OSSL_CMP_CTX *ctx)
{
return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_CR,
CMP_R_ERROR_CREATING_CR, OSSL_CMP_PKIBODY_CP);
}
X509 *OSSL_CMP_exec_KUR_ses(OSSL_CMP_CTX *ctx)
{
return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_KUR,
CMP_R_ERROR_CREATING_KUR, OSSL_CMP_PKIBODY_KUP);
}
X509 *OSSL_CMP_exec_P10CR_ses(OSSL_CMP_CTX *ctx)
{
return do_certreq_seq(ctx, OSSL_CMP_PKIBODY_P10CR,
CMP_R_ERROR_CREATING_P10CR, OSSL_CMP_PKIBODY_CP);
}
X509 *OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *rr = NULL;
OSSL_CMP_MSG *rp = NULL;
const int num_RevDetails = 1;
const int rsid = OSSL_CMP_REVREQSID;
OSSL_CMP_REVREPCONTENT *rrep = NULL;
OSSL_CMP_PKISI *si = NULL;
char buf[OSSL_CMP_PKISI_BUFLEN];
X509 *result = NULL;
if (ctx == NULL) {
CMPerr(0, CMP_R_INVALID_ARGS);
return 0;
}
ctx->status = -1;
/* OSSL_CMP_rr_new() also checks if all necessary options are set */
if ((rr = ossl_cmp_rr_new(ctx)) == NULL)
goto end;
if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP))
goto end;
rrep = rp->body->value.rp;
if (sk_OSSL_CMP_PKISI_num(rrep->status) != num_RevDetails) {
CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
goto end;
}
/* evaluate PKIStatus field */
si = ossl_cmp_revrepcontent_get_pkisi(rrep, rsid);
if (!save_statusInfo(ctx, si))
goto err;
switch (ossl_cmp_pkisi_get_status(si)) {
case OSSL_CMP_PKISTATUS_accepted:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=accepted)");
result = ctx->oldCert;
break;
case OSSL_CMP_PKISTATUS_grantedWithMods:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=grantedWithMods)");
result = ctx->oldCert;
break;
case OSSL_CMP_PKISTATUS_rejection:
CMPerr(0, CMP_R_REQUEST_REJECTED_BY_SERVER);
goto err;
case OSSL_CMP_PKISTATUS_revocationWarning:
ossl_cmp_info(ctx, "revocation accepted (PKIStatus=revocationWarning)");
result = ctx->oldCert;
break;
case OSSL_CMP_PKISTATUS_revocationNotification:
/* interpretation as warning or error depends on CA */
ossl_cmp_warn(ctx,
"revocation accepted (PKIStatus=revocationNotification)");
result = ctx->oldCert;
break;
case OSSL_CMP_PKISTATUS_waiting:
case OSSL_CMP_PKISTATUS_keyUpdateWarning:
CMPerr(0, CMP_R_UNEXPECTED_PKISTATUS);
goto err;
default:
CMPerr(0, CMP_R_UNKNOWN_PKISTATUS);
goto err;
}
/* check any present CertId in optional revCerts field */
if (rrep->revCerts != NULL) {
OSSL_CRMF_CERTID *cid;
OSSL_CRMF_CERTTEMPLATE *tmpl =
sk_OSSL_CMP_REVDETAILS_value(rr->body->value.rr, rsid)->certDetails;
const X509_NAME *issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
ASN1_INTEGER *serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
if (sk_OSSL_CRMF_CERTID_num(rrep->revCerts) != num_RevDetails) {
CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
result = NULL;
goto err;
}
if ((cid = ossl_cmp_revrepcontent_get_CertId(rrep, rsid)) == NULL) {
result = NULL;
goto err;
}
if (X509_NAME_cmp(issuer, OSSL_CRMF_CERTID_get0_issuer(cid)) != 0) {
CMPerr(0, CMP_R_WRONG_CERTID_IN_RP);
result = NULL;
goto err;
}
if (ASN1_INTEGER_cmp(serial,
OSSL_CRMF_CERTID_get0_serialNumber(cid)) != 0) {
CMPerr(0, CMP_R_WRONG_SERIAL_IN_RP);
result = NULL;
goto err;
}
}
/* check number of any optionally present crls */
if (rrep->crls != NULL && sk_X509_CRL_num(rrep->crls) != num_RevDetails) {
CMPerr(0, CMP_R_WRONG_RP_COMPONENT_COUNT);
result = NULL;
goto err;
}
err:
if (result == NULL
&& OSSL_CMP_CTX_snprint_PKIStatus(ctx, buf, sizeof(buf)) != NULL)
ERR_add_error_data(1, buf);
end:
OSSL_CMP_MSG_free(rr);
OSSL_CMP_MSG_free(rp);
return result;
}
STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx)
{
OSSL_CMP_MSG *genm;
OSSL_CMP_MSG *genp = NULL;
STACK_OF(OSSL_CMP_ITAV) *rcvd_itavs = NULL;
if (ctx == NULL) {
CMPerr(0, CMP_R_INVALID_ARGS);
return 0;
}
if ((genm = ossl_cmp_genm_new(ctx)) == NULL)
goto err;
if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP))
goto err;
/* received stack of itavs not to be freed with the genp */
rcvd_itavs = genp->body->value.genp;
genp->body->value.genp = NULL;
err:
OSSL_CMP_MSG_free(genm);
OSSL_CMP_MSG_free(genp);
return rcvd_itavs; /* recv_itavs == NULL indicates an error */
}
+59 -170
View File
@@ -20,9 +20,7 @@
#include <openssl/crmf.h>
#include <openssl/err.h>
/*
* Get current certificate store containing trusted root CA certs
*/
/* Get current certificate store containing trusted root CA certs */
X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -36,7 +34,6 @@ X509_STORE *OSSL_CMP_CTX_get0_trustedStore(const OSSL_CMP_CTX *ctx)
* Set certificate store containing trusted (root) CA certs and possibly CRLs
* and a cert verification callback function used for CMP server authentication.
* Any already existing store entry is freed. Given NULL, the entry is reset.
* returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
{
@@ -49,9 +46,7 @@ int OSSL_CMP_CTX_set0_trustedStore(OSSL_CMP_CTX *ctx, X509_STORE *store)
return 1;
}
/*
* Get current list of non-trusted intermediate certs
*/
/* Get current list of non-trusted intermediate certs */
STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -64,7 +59,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get0_untrusted_certs(const OSSL_CMP_CTX *ctx)
/*
* Set untrusted certificates for path construction in authentication of
* the CMP server and potentially others (TLS server, newly enrolled cert).
* returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_untrusted_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs)
{
@@ -101,9 +95,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void)
ctx->status = -1;
ctx->failInfoCode = -1;
ctx->serverPort = OSSL_CMP_DEFAULT_PORT;
ctx->proxyPort = OSSL_CMP_DEFAULT_PORT;
ctx->msgtimeout = 2 * 60;
ctx->msg_timeout = 2 * 60;
if ((ctx->untrusted_certs = sk_X509_new_null()) == NULL)
goto err;
@@ -125,9 +117,7 @@ OSSL_CMP_CTX *OSSL_CMP_CTX_new(void)
return NULL;
}
/*
* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX
*/
/* Prepare the OSSL_CMP_CTX for next use, partly re-initializing OSSL_CMP_CTX */
int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL) {
@@ -148,17 +138,16 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx)
&& ossl_cmp_ctx_set1_recipNonce(ctx, NULL);
}
/*
* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new()
*/
/* Frees OSSL_CMP_CTX variables allocated in OSSL_CMP_CTX_new() */
void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx)
{
if (ctx == NULL)
return;
OPENSSL_free(ctx->serverPath);
OPENSSL_free(ctx->serverName);
OPENSSL_free(ctx->proxyName);
OPENSSL_free(ctx->server);
OPENSSL_free(ctx->proxy);
OPENSSL_free(ctx->no_proxy);
X509_free(ctx->srvCert);
X509_free(ctx->validatedSrvCert);
@@ -252,12 +241,8 @@ int ossl_cmp_ctx_set0_validatedSrvCert(OSSL_CMP_CTX *ctx, X509 *cert)
return 1;
}
/*
* Set callback function for checking if the cert is ok or should
* it be rejected.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb)
/* Set callback function for checking if the cert is ok or should be rejected */
int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_certConf_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
@@ -270,7 +255,6 @@ int OSSL_CMP_CTX_set_certConf_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_certConf_cb_t cb)
/*
* Set argument, respectively a pointer to a structure containing arguments,
* optionally to be used by the certConf callback.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_certConf_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
@@ -380,11 +364,8 @@ int ossl_cmp_print_log(OSSL_CMP_severity level, const OSSL_CMP_CTX *ctx,
return res;
}
/*
* Set a callback function for error reporting and logging messages.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_log_cb_t cb)
/* Set a callback function for error reporting and logging messages */
int OSSL_CMP_CTX_set_log_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_log_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
@@ -411,7 +392,6 @@ void OSSL_CMP_CTX_print_errors(OSSL_CMP_CTX *ctx)
/*
* Set or clear the reference value to be used for identification
* (i.e., the user name) when using PBMAC.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
const unsigned char *ref, int len)
@@ -424,10 +404,7 @@ int OSSL_CMP_CTX_set1_referenceValue(OSSL_CMP_CTX *ctx,
len);
}
/*
* Set or clear the password to be used for protecting messages with PBMAC.
* Returns 1 on success, 0 on error
*/
/* Set or clear the password to be used for protecting messages with PBMAC */
int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, const unsigned char *sec,
const int len)
{
@@ -465,7 +442,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_extraCertsIn(const OSSL_CMP_CTX *ctx)
/*
* Copies any given stack of inbound X509 certificates to extraCertsIn
* of the OSSL_CMP_CTX structure so that they may be retrieved later.
* Returns 1 on success, 0 on error.
*/
int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsIn)
@@ -483,7 +459,6 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx,
/*
* Duplicate and set the given stack as the new stack of X509
* certificates to send out in the extraCerts field.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
STACK_OF(X509) *extraCertsOut)
@@ -503,7 +478,6 @@ int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx,
/*
* Add the given policy info object
* to the X509_EXTENSIONS of the requested certificate template.
* Returns 1 on success, 0 on error.
*/
int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
{
@@ -519,9 +493,7 @@ int OSSL_CMP_CTX_push0_policy(OSSL_CMP_CTX *ctx, POLICYINFO *pinfo)
return sk_POLICYINFO_push(ctx->policies, pinfo);
}
/*
* Add an ITAV for geninfo of the PKI message header
*/
/* Add an ITAV for geninfo of the PKI message header */
int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
@@ -531,9 +503,7 @@ int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
return OSSL_CMP_ITAV_push0_stack_item(&ctx->geninfo_ITAVs, itav);
}
/*
* Add an itav for the body of outgoing general messages
*/
/* Add an itav for the body of outgoing general messages */
int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav)
{
if (ctx == NULL) {
@@ -562,7 +532,6 @@ STACK_OF(X509) *OSSL_CMP_CTX_get1_caPubs(const OSSL_CMP_CTX *ctx)
/*
* Duplicate and copy the given stack of certificates to the given
* OSSL_CMP_CTX structure so that they may be retrieved later.
* Returns 1 on success, 0 on error
*/
int ossl_cmp_ctx_set1_caPubs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *caPubs)
{
@@ -614,39 +583,25 @@ int OSSL_CMP_CTX_set1_##FIELD(OSSL_CMP_CTX *ctx, TYPE *val) \
* Pins the server certificate to be directly trusted (even if it is expired)
* for verifying response messages.
* Cert pointer is not consumed. It may be NULL to clear the entry.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(srvCert, X509)
/*
* Set the X509 name of the recipient. Set in the PKIHeader.
* returns 1 on success, 0 on error
*/
/* Set the X509 name of the recipient. Set in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(recipient, X509_NAME)
/*
* Store the X509 name of the expected sender in the PKIHeader of responses.
* Returns 1 on success, 0 on error
*/
/* Store the X509 name of the expected sender in the PKIHeader of responses */
DEFINE_OSSL_CMP_CTX_set1(expected_sender, X509_NAME)
/*
* Set the X509 name of the issuer. Set in the PKIHeader.
* Returns 1 on success, 0 on error
*/
/* Set the X509 name of the issuer. Set in the PKIHeader */
DEFINE_OSSL_CMP_CTX_set1(issuer, X509_NAME)
/*
* Set the subject name that will be placed in the certificate
* request. This will be the subject name on the received certificate.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(subjectName, X509_NAME)
/*
* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR.
* Returns 1 on success, 0 on error
*/
/* Set the X.509v3 certificate request extensions to be used in IR/CR/KUR */
int OSSL_CMP_CTX_set0_reqExtensions(OSSL_CMP_CTX *ctx, X509_EXTENSIONS *exts)
{
if (ctx == NULL) {
@@ -680,7 +635,6 @@ int OSSL_CMP_CTX_reqExtensions_have_SAN(OSSL_CMP_CTX *ctx)
/*
* Add a GENERAL_NAME structure that will be added to the CRMF
* request's extensions field to request subject alternative names.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
const GENERAL_NAME *name)
@@ -712,7 +666,6 @@ int OSSL_CMP_CTX_push1_subjectAltName(OSSL_CMP_CTX *ctx,
/*
* Set our own client certificate, used for example in KUR and when
* doing the IR with existing certificate.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509)
@@ -721,19 +674,14 @@ DEFINE_OSSL_CMP_CTX_set1_up_ref(clCert, X509)
* or the certificate to be revoked in RR, respectively.
* Also used as reference cert (defaulting to clCert) for deriving subject DN
* and SANs. Its issuer is used as default recipient in the CMP message header.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1_up_ref(oldCert, X509)
/*
* Set the PKCS#10 CSR to be sent in P10CR.
* Returns 1 on success, 0 on error
*/
/* Set the PKCS#10 CSR to be sent in P10CR */
DEFINE_OSSL_CMP_CTX_set1(p10CSR, X509_REQ)
/*
* Sets the (newly received in IP/KUP/CP) certificate in the context.
* Returns 1 on success, 0 on error
* Set the (newly received in IP/KUP/CP) certificate in the context.
* TODO: this only permits for one cert to be enrolled at a time.
*/
int ossl_cmp_ctx_set0_newCert(OSSL_CMP_CTX *ctx, X509 *cert)
@@ -759,16 +707,10 @@ X509 *OSSL_CMP_CTX_get0_newCert(const OSSL_CMP_CTX *ctx)
return ctx->newCert;
}
/*
* Set the client's current private key.
* Returns 1 on success, 0 on error
*/
/* Set the client's current private key */
DEFINE_OSSL_CMP_CTX_set1_up_ref(pkey, EVP_PKEY)
/*
* Set new key pair. Used e.g. when doing Key Update.
* Returns 1 on success, 0 on error
*/
/* Set new key pair. Used e.g. when doing Key Update */
int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
{
if (ctx == NULL) {
@@ -782,9 +724,7 @@ int OSSL_CMP_CTX_set0_newPkey(OSSL_CMP_CTX *ctx, int priv, EVP_PKEY *pkey)
return 1;
}
/*
* gets the private/public key to use for certificate enrollment, NULL on error
*/
/* Get the private/public key to use for cert enrollment, or NULL on error */
EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
{
if (ctx == NULL) {
@@ -799,10 +739,7 @@ EVP_PKEY *OSSL_CMP_CTX_get0_newPkey(const OSSL_CMP_CTX *ctx, int priv)
return ctx->pkey; /* may be NULL */
}
/*
* Sets the given transactionID to the context.
* Returns 1 on success, 0 on error
*/
/* Set the given transactionID to the context */
int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *id)
{
@@ -813,11 +750,7 @@ int OSSL_CMP_CTX_set1_transactionID(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->transactionID, id);
}
/*
* sets the given nonce to be used for the recipNonce in the next message to be
* created.
* returns 1 on success, 0 on error
*/
/* Set the nonce to be used for the recipNonce in the message created next */
int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
@@ -826,10 +759,7 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->recipNonce, nonce);
}
/*
* Stores the given nonce as the last senderNonce sent out.
* Returns 1 on success, 0 on error
*/
/* Stores the given nonce as the last senderNonce sent out */
int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce)
{
@@ -840,36 +770,16 @@ int OSSL_CMP_CTX_set1_senderNonce(OSSL_CMP_CTX *ctx,
return ossl_cmp_asn1_octet_string_set1(&ctx->senderNonce, nonce);
}
/*
* Set the host name of the (HTTP) proxy server to use for all connections
* returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(proxyName, char)
/* Set the proxy server to use for HTTP(S) connections */
DEFINE_OSSL_CMP_CTX_set1(proxy, char)
/*
* Set the (HTTP) host name of the CA server.
* Returns 1 on success, 0 on error
*/
DEFINE_OSSL_CMP_CTX_set1(serverName, char)
/* Set the (HTTP) host name of the CMP server */
DEFINE_OSSL_CMP_CTX_set1(server, char)
/*
* Sets the (HTTP) proxy port to be used.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_proxyPort(OSSL_CMP_CTX *ctx, int port)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx->proxyPort = port;
return 1;
}
/* Set the server exclusion list of the HTTP proxy server */
DEFINE_OSSL_CMP_CTX_set1(no_proxy, char)
/*
* sets the http connect/disconnect callback function to be used for HTTP(S)
* returns 1 on success, 0 on error
*/
/* Set the http connect/disconnect callback function to be used for HTTP(S) */
int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
{
if (ctx == NULL) {
@@ -880,10 +790,7 @@ int OSSL_CMP_CTX_set_http_cb(OSSL_CMP_CTX *ctx, OSSL_HTTP_bio_cb_t cb)
return 1;
}
/*
* Set argument optionally to be used by the http connect/disconnect callback.
* Returns 1 on success, 0 on error
*/
/* Set argument optionally to be used by the http connect/disconnect callback */
int OSSL_CMP_CTX_set_http_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
@@ -907,11 +814,8 @@ void *OSSL_CMP_CTX_get_http_cb_arg(const OSSL_CMP_CTX *ctx)
return ctx->http_cb_arg;
}
/*
* Set callback function for sending CMP request and receiving response.
* Returns 1 on success, 0 on error
*/
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb)
/* Set callback function for sending CMP request and receiving response */
int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_CMP_transfer_cb_t cb)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
@@ -921,10 +825,7 @@ int OSSL_CMP_CTX_set_transfer_cb(OSSL_CMP_CTX *ctx, OSSL_cmp_transfer_cb_t cb)
return 1;
}
/*
* Set argument optionally to be used by the transfer callback.
* Returns 1 on success, 0 on error
*/
/* Set argument optionally to be used by the transfer callback */
int OSSL_CMP_CTX_set_transfer_cb_arg(OSSL_CMP_CTX *ctx, void *arg)
{
if (ctx == NULL) {
@@ -948,10 +849,7 @@ void *OSSL_CMP_CTX_get_transfer_cb_arg(const OSSL_CMP_CTX *ctx)
return ctx->transfer_cb_arg;
}
/*
* Sets the (HTTP) server port to be used.
* Returns 1 on success, 0 on error
*/
/** Set the HTTP server port to be used */
int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
{
if (ctx == NULL) {
@@ -962,16 +860,10 @@ int OSSL_CMP_CTX_set_serverPort(OSSL_CMP_CTX *ctx, int port)
return 1;
}
/*
* Sets the HTTP path to be used on the server (e.g "pkix/").
* Returns 1 on success, 0 on error
*/
/* Set the HTTP path to be used on the server (e.g "pkix/") */
DEFINE_OSSL_CMP_CTX_set1(serverPath, char)
/*
* Set the failInfo error code as bit encoding in OSSL_CMP_CTX.
* Returns 1 on success, 0 on error
*/
/* Set the failInfo error code as bit encoding in OSSL_CMP_CTX */
int ossl_cmp_ctx_set_failInfoCode(OSSL_CMP_CTX *ctx, int fail_info)
{
if (!ossl_assert(ctx != NULL))
@@ -993,10 +885,7 @@ int OSSL_CMP_CTX_get_failInfoCode(const OSSL_CMP_CTX *ctx)
return ctx->failInfoCode;
}
/*
* Sets a Boolean or integer option of the context to the "val" arg.
* Returns 1 on success, 0 on error
*/
/* Set a Boolean or integer option of the context to the "val" arg */
int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
{
int min_val;
@@ -1010,7 +899,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_REVOCATION_REASON:
min_val = OCSP_REVOKED_STATUS_NOSTATUS;
break;
case OSSL_CMP_OPT_POPOMETHOD:
case OSSL_CMP_OPT_POPO_METHOD:
min_val = OSSL_CRMF_POPO_NONE;
break;
default:
@@ -1030,10 +919,10 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
}
ctx->log_verbosity = val;
break;
case OSSL_CMP_OPT_IMPLICITCONFIRM:
case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
ctx->implicitConfirm = val;
break;
case OSSL_CMP_OPT_DISABLECONFIRM:
case OSSL_CMP_OPT_DISABLE_CONFIRM:
ctx->disableConfirm = val;
break;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
@@ -1042,7 +931,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
ctx->unprotectedErrors = val;
break;
case OSSL_CMP_OPT_VALIDITYDAYS:
case OSSL_CMP_OPT_VALIDITY_DAYS:
ctx->days = val;
break;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
@@ -1057,7 +946,7 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
ctx->ignore_keyusage = val;
break;
case OSSL_CMP_OPT_POPOMETHOD:
case OSSL_CMP_OPT_POPO_METHOD:
if (val > OSSL_CRMF_POPO_KEYAGREE) {
CMPerr(0, CMP_R_INVALID_ARGS);
return 0;
@@ -1073,11 +962,11 @@ int OSSL_CMP_CTX_set_option(OSSL_CMP_CTX *ctx, int opt, int val)
case OSSL_CMP_OPT_MAC_ALGNID:
ctx->pbm_mac = val;
break;
case OSSL_CMP_OPT_MSGTIMEOUT:
ctx->msgtimeout = val;
case OSSL_CMP_OPT_MSG_TIMEOUT:
ctx->msg_timeout = val;
break;
case OSSL_CMP_OPT_TOTALTIMEOUT:
ctx->totaltimeout = val;
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
ctx->total_timeout = val;
break;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
ctx->permitTAInExtraCertsForIR = val;
@@ -1111,15 +1000,15 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
switch (opt) {
case OSSL_CMP_OPT_LOG_VERBOSITY:
return ctx->log_verbosity;
case OSSL_CMP_OPT_IMPLICITCONFIRM:
case OSSL_CMP_OPT_IMPLICIT_CONFIRM:
return ctx->implicitConfirm;
case OSSL_CMP_OPT_DISABLECONFIRM:
case OSSL_CMP_OPT_DISABLE_CONFIRM:
return ctx->disableConfirm;
case OSSL_CMP_OPT_UNPROTECTED_SEND:
return ctx->unprotectedSend;
case OSSL_CMP_OPT_UNPROTECTED_ERRORS:
return ctx->unprotectedErrors;
case OSSL_CMP_OPT_VALIDITYDAYS:
case OSSL_CMP_OPT_VALIDITY_DAYS:
return ctx->days;
case OSSL_CMP_OPT_SUBJECTALTNAME_NODEFAULT:
return ctx->SubjectAltName_nodefault;
@@ -1129,7 +1018,7 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
return ctx->setPoliciesCritical;
case OSSL_CMP_OPT_IGNORE_KEYUSAGE:
return ctx->ignore_keyusage;
case OSSL_CMP_OPT_POPOMETHOD:
case OSSL_CMP_OPT_POPO_METHOD:
return ctx->popoMethod;
case OSSL_CMP_OPT_DIGEST_ALGNID:
return ctx->digest;
@@ -1137,10 +1026,10 @@ int OSSL_CMP_CTX_get_option(const OSSL_CMP_CTX *ctx, int opt)
return ctx->pbm_owf;
case OSSL_CMP_OPT_MAC_ALGNID:
return ctx->pbm_mac;
case OSSL_CMP_OPT_MSGTIMEOUT:
return ctx->msgtimeout;
case OSSL_CMP_OPT_TOTALTIMEOUT:
return ctx->totaltimeout;
case OSSL_CMP_OPT_MSG_TIMEOUT:
return ctx->msg_timeout;
case OSSL_CMP_OPT_TOTAL_TIMEOUT:
return ctx->total_timeout;
case OSSL_CMP_OPT_PERMIT_TA_IN_EXTRACERTS_FOR_IR:
return ctx->permitTAInExtraCertsForIR;
case OSSL_CMP_OPT_REVOCATION_REASON:
+40 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -16,26 +16,44 @@
static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ALGORITHM_NOT_SUPPORTED),
"algorithm not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_CHECKAFTER_IN_POLLREP),
"bad checkafter in pollrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_BAD_REQUEST_ID), "bad request id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTHASH_UNMATCHED), "certhash unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTID_NOT_FOUND), "certid not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_ACCEPTED),
"certificate not accepted"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTIFICATE_NOT_FOUND),
"certificate not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTREQMSG_NOT_FOUND),
"certreqmsg not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERTRESPONSE_NOT_FOUND),
"certresponse not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CERT_AND_KEY_DO_NOT_MATCH),
"cert and key do not match"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKAFTER_OUT_OF_RANGE),
"checkafter out of range"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE),
"checking pbm no secret available"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_KEYUPDATEWARNING),
"encountered keyupdatewarning"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ENCOUNTERED_WAITING),
"encountered waiting"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CALCULATING_PROTECTION),
"error calculating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTCONF),
"error creating certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CERTREP),
"error creating certrep"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_CR), "error creating cr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_ERROR),
"error creating error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENM),
"error creating genm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_GENP),
"error creating genp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_IR), "error creating ir"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_KUR), "error creating kur"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_P10CR),
"error creating p10cr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_PKICONF),
@@ -48,10 +66,14 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_CREATING_RR), "error creating rr"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PARSING_PKISTATUS),
"error parsing pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROCESSING_MESSAGE),
"error processing message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_PROTECTING_MESSAGE),
"error protecting message"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_SETTING_CERTHASH),
"error setting certhash"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_UNEXPECTED_CERTCONF),
"error unexpected certconf"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_PROTECTION),
"error validating protection"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY),
@@ -72,6 +94,10 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"missing sender identification"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MISSING_TRUST_STORE),
"missing trust store"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED),
"multiple requests not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED),
"multiple responses not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_MULTIPLE_SAN_SOURCES),
"multiple san sources"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_NO_STDIO), "no stdio"},
@@ -81,23 +107,32 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKIBODY_ERROR), "pkibody error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_PKISTATUSINFO_NOT_FOUND),
"pkistatusinfo not found"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POLLING_FAILED), "polling failed"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE),
"potentially invalid certificate"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECEIVED_ERROR), "received error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_RECIPNONCE_UNMATCHED),
"recipnonce unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_NOT_ACCEPTED),
"request not accepted"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_REQUEST_REJECTED_BY_SERVER),
"request rejected by server"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED),
"sender generalname type not supported"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG),
"srvcert does not validate msg"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TOTAL_TIMEOUT), "total timeout"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSACTIONID_UNMATCHED),
"transactionid unmatched"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS),
"unexpected pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID),
"unknown algorithm id"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_CERT_TYPE), "unknown cert type"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_PKISTATUS), "unknown pkistatus"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_ALGORITHM),
"unsupported algorithm"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE),
@@ -106,7 +141,11 @@ static const ERR_STRING_DATA CMP_str_reasons[] = {
"unsupported protection alg dhbasedmac"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_ALGORITHM_OID),
"wrong algorithm oid"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_CERTID_IN_RP), "wrong certid in rp"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_PBM_VALUE), "wrong pbm value"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_RP_COMPONENT_COUNT),
"wrong rp component count"},
{ERR_PACK(ERR_LIB_CMP, 0, CMP_R_WRONG_SERIAL_IN_RP), "wrong serial in rp"},
{0, NULL}
};
+27 -41
View File
@@ -63,31 +63,42 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr)
return hdr->recipNonce;
}
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name)
{
X509_NAME *null = X509_NAME_new();
int res = name == NULL || null == NULL
|| (name->type == GEN_DIRNAME
&& X509_NAME_cmp(name->d.directoryName, null) == 0);
X509_NAME_free(null);
return res;
}
/* assign to *tgt a copy of src (which may be NULL to indicate an empty DN) */
static int set1_general_name(GENERAL_NAME **tgt, const X509_NAME *src)
{
GENERAL_NAME *gen;
GENERAL_NAME *name;
if (!ossl_assert(tgt != NULL))
return 0;
if ((gen = GENERAL_NAME_new()) == NULL)
if ((name = GENERAL_NAME_new()) == NULL)
goto err;
gen->type = GEN_DIRNAME;
name->type = GEN_DIRNAME;
if (src == NULL) { /* NULL-DN */
if ((gen->d.directoryName = X509_NAME_new()) == NULL)
if ((name->d.directoryName = X509_NAME_new()) == NULL)
goto err;
} else if (!X509_NAME_set(&gen->d.directoryName, src)) {
} else if (!X509_NAME_set(&name->d.directoryName, src)) {
goto err;
}
GENERAL_NAME_free(*tgt);
*tgt = gen;
*tgt = name;
return 1;
err:
GENERAL_NAME_free(gen);
GENERAL_NAME_free(name);
return 0;
}
@@ -153,25 +164,6 @@ int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
}
/* push the given text string to the given PKIFREETEXT ft */
int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text)
{
ASN1_UTF8STRING *utf8string;
if (!ossl_assert(ft != NULL && text != NULL))
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
return 0;
if (!ASN1_STRING_set(utf8string, text, -1))
goto err;
if (!sk_ASN1_UTF8STRING_push(ft, utf8string))
goto err;
return 1;
err:
ASN1_UTF8STRING_free(utf8string);
return 0;
}
int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
{
if (!ossl_assert(hdr != NULL && text != NULL))
@@ -193,7 +185,8 @@ int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text)
&& (hdr->freeText = sk_ASN1_UTF8STRING_new_null()) == NULL)
return 0;
return ossl_cmp_pkifreetext_push_str(hdr->freeText, (char *)text->data);
return
ossl_cmp_sk_ASN1_UTF8STRING_push_str(hdr->freeText, (char *)text->data);
}
int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
@@ -205,7 +198,7 @@ int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
}
int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
STACK_OF(OSSL_CMP_ITAV) *itavs)
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i;
OSSL_CMP_ITAV *itav;
@@ -250,7 +243,7 @@ int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr)
}
/* return 1 if implicitConfirm in the generalInfo field of the header is set */
int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
{
int itavCount;
int i;
@@ -273,8 +266,8 @@ int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr)
/* fill in all fields of the hdr according to the info given in ctx */
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
{
X509_NAME *sender;
X509_NAME *rcp = NULL;
const X509_NAME *sender;
const X509_NAME *rcp = NULL;
if (!ossl_assert(ctx != NULL && hdr != NULL))
return 0;
@@ -283,19 +276,12 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr)
if (!ossl_cmp_hdr_set_pvno(hdr, OSSL_CMP_PVNO))
return 0;
sender = ctx->clCert != NULL ?
X509_get_subject_name(ctx->clCert) : ctx->subjectName;
/*
* The sender name is copied from the subject of the client cert, if any,
* or else from the the subject name provided for certification requests.
* As required by RFC 4210 section 5.1.1., if the sender name is not known
* to the client it set to NULL-DN. In this case for identification at least
* the senderKID must be set, which we take from any referenceValue given.
* or else from the subject name provided for certification requests.
*/
if (sender == NULL && ctx->referenceValue == NULL) {
CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION);
return 0;
}
sender = ctx->clCert != NULL ?
X509_get_subject_name(ctx->clCert) : ctx->subjectName;
if (!ossl_cmp_hdr_set1_sender(hdr, sender))
return 0;
+66
View File
@@ -0,0 +1,66 @@
/*
* Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <stdio.h>
#include <openssl/asn1t.h>
#include <openssl/http.h>
#include "internal/sockets.h"
#include "openssl/cmp.h"
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/cmp.h>
#include <openssl/err.h>
/*
* Send the PKIMessage req and on success return the response, else NULL.
* Any previous error queue entries will likely be removed by ERR_clear_error().
*/
OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req)
{
char server_port[32] = { '\0' };
STACK_OF(CONF_VALUE) *headers = NULL;
const char *const content_type_pkix = "application/pkixcmp";
OSSL_CMP_MSG *res;
if (ctx == NULL || req == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
if (!X509V3_add_value("Pragma", "no-cache", &headers))
return NULL;
if (ctx->serverPort != 0)
BIO_snprintf(server_port, sizeof(server_port), "%d", ctx->serverPort);
res = (OSSL_CMP_MSG *)
OSSL_HTTP_post_asn1(ctx->server, server_port, ctx->serverPath,
OSSL_CMP_CTX_get_http_cb_arg(ctx) != NULL,
ctx->proxy, ctx->no_proxy, NULL, NULL,
ctx->http_cb, OSSL_CMP_CTX_get_http_cb_arg(ctx),
headers, content_type_pkix,
(ASN1_VALUE *)req, ASN1_ITEM_rptr(OSSL_CMP_MSG),
0, 0, ctx->msg_timeout, content_type_pkix,
ASN1_ITEM_rptr(OSSL_CMP_MSG));
sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
return res;
}
+42 -49
View File
@@ -28,20 +28,20 @@
* this structure is used to store the context for CMP sessions
*/
struct ossl_cmp_ctx_st {
OSSL_cmp_log_cb_t log_cb; /* log callback for error/debug/etc. output */
OSSL_CMP_log_cb_t log_cb; /* log callback for error/debug/etc. output */
OSSL_CMP_severity log_verbosity; /* level of verbosity of log output */
/* message transfer */
OSSL_cmp_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
OSSL_CMP_transfer_cb_t transfer_cb; /* default: OSSL_CMP_MSG_http_perform */
void *transfer_cb_arg; /* allows to store optional argument to cb */
/* HTTP-based transfer */
char *serverPath;
char *serverName;
char *server;
int serverPort;
char *proxyName;
int proxyPort;
int msgtimeout; /* max seconds to wait for each CMP message round trip */
int totaltimeout; /* maximum number seconds an enrollment may take, incl. */
char *proxy;
char *no_proxy;
int msg_timeout; /* max seconds to wait for each CMP message round trip */
int total_timeout; /* max number of seconds an enrollment may take, incl. */
/* attempts polling for a response if a 'waiting' PKIStatus is received */
time_t end_time; /* session start time + totaltimeout */
OSSL_HTTP_bio_cb_t http_cb;
@@ -56,7 +56,7 @@ struct ossl_cmp_ctx_st {
int unprotectedErrors;
X509 *srvCert; /* certificate used to identify the server */
X509 *validatedSrvCert; /* caches any already validated server cert */
X509_NAME *expected_sender; /* expected sender in pkiheader of response */
X509_NAME *expected_sender; /* expected sender in header of response */
X509_STORE *trusted; /* trust store maybe w CRLs and cert verify callback */
STACK_OF(X509) *untrusted_certs; /* untrusted (intermediate) certs */
int ignore_keyusage; /* ignore key usage entry when validating certs */
@@ -95,7 +95,7 @@ struct ossl_cmp_ctx_st {
int newPkey_priv; /* flag indicating if newPkey contains private key */
X509_NAME *issuer; /* issuer name to used in cert template */
int days; /* Number of days new certificates are asked to be valid for */
X509_NAME *subjectName; /* subject name to be used in the cert template */
X509_NAME *subjectName; /* subject name to be used in cert template */
STACK_OF(GENERAL_NAME) *subjectAltNames; /* to add to the cert template */
int SubjectAltName_nodefault;
int setSubjectAltNameCritical;
@@ -122,7 +122,7 @@ struct ossl_cmp_ctx_st {
STACK_OF(X509) *extraCertsIn; /* extraCerts received from server */
/* certificate confirmation */
OSSL_cmp_certConf_cb_t certConf_cb; /* callback for app checking new cert */
OSSL_CMP_certConf_cb_t certConf_cb; /* callback for app checking new cert */
void *certConf_cb_arg; /* allows to store an argument individual to cb */
} /* OSSL_CMP_CTX */;
@@ -246,7 +246,6 @@ struct ossl_cmp_itav_st {
} infoValue;
} /* OSSL_CMP_ITAV */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_ITAV)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_ITAV)
typedef struct ossl_cmp_certorenccert_st {
int type;
@@ -284,8 +283,6 @@ struct ossl_cmp_pkisi_st {
OSSL_CMP_PKIFREETEXT *statusString;
OSSL_CMP_PKIFAILUREINFO *failInfo;
} /* OSSL_CMP_PKISI */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_PKISI)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_PKISI)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
/*-
@@ -296,10 +293,11 @@ DECLARE_ASN1_DUP_FUNCTION(OSSL_CRMF_CERTID)
* crlEntryDetails Extensions OPTIONAL
* }
*/
typedef struct ossl_cmp_revdetails_st {
struct ossl_cmp_revdetails_st {
OSSL_CRMF_CERTTEMPLATE *certDetails;
X509_EXTENSIONS *crlEntryDetails;
} OSSL_CMP_REVDETAILS;
} /* OSSL_CMP_REVDETAILS */;
typedef struct ossl_cmp_revdetails_st OSSL_CMP_REVDETAILS;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_REVDETAILS)
DEFINE_STACK_OF(OSSL_CMP_REVDETAILS)
@@ -375,7 +373,6 @@ struct ossl_cmp_certstatus_st {
OSSL_CMP_PKISI *statusInfo;
} /* OSSL_CMP_CERTSTATUS */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTSTATUS)
typedef STACK_OF(OSSL_CMP_CERTSTATUS) OSSL_CMP_CERTCONFIRMCONTENT;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_CERTCONFIRMCONTENT)
@@ -670,7 +667,6 @@ struct ossl_cmp_msg_st {
STACK_OF(X509) *extraCerts; /* 1 */
} /* OSSL_CMP_MSG */;
DECLARE_ASN1_FUNCTIONS(OSSL_CMP_MSG)
DECLARE_ASN1_DUP_FUNCTION(OSSL_CMP_MSG)
/*-
* ProtectedPart ::= SEQUENCE {
@@ -728,17 +724,6 @@ DECLARE_ASN1_FUNCTIONS(CMP_PROTECTEDPART)
* }
*/
/*
* constants
*/
/* certReqId for the first - and so far only - certificate request */
# define OSSL_CMP_CERTREQID 0
/* sequence id for the first - and so far only - revocation request */
# define OSSL_CMP_REVREQSID 0
/*
* functions
*/
/* from cmp_asn.c */
int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a);
@@ -755,6 +740,9 @@ int ossl_cmp_sk_X509_add1_certs(STACK_OF(X509) *sk, STACK_OF(X509) *certs,
int no_self_issued, int no_dups, int prepend);
int ossl_cmp_X509_STORE_add1_certs(X509_STORE *store, STACK_OF(X509) *certs,
int only_self_issued);
STACK_OF(X509) *ossl_cmp_X509_STORE_get1_certs(X509_STORE *store);
int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
const char *text);
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src);
int ossl_cmp_asn1_octet_string_set1_bytes(ASN1_OCTET_STRING **tgt,
@@ -800,32 +788,30 @@ int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx,
const ASN1_OCTET_STRING *nonce);
/* from cmp_status.c */
OSSL_CMP_PKISI *
ossl_cmp_statusinfo_new(int status, int fail_info, const char *text);
int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *statusInfo);
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si);
const char *ossl_cmp_PKIStatus_to_string(int status);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si);
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si);
int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index);
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int index);
/* from cmp_hdr.c */
int ossl_cmp_hdr_set_pvno(OSSL_CMP_PKIHEADER *hdr, int pvno);
int ossl_cmp_hdr_get_pvno(const OSSL_CMP_PKIHEADER *hdr);
ASN1_OCTET_STRING *ossl_cmp_hdr_get0_senderNonce(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name);
int ossl_cmp_hdr_set1_sender(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_set1_recipient(OSSL_CMP_PKIHEADER *hdr, const X509_NAME *nm);
int ossl_cmp_hdr_update_messageTime(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_set1_senderKID(OSSL_CMP_PKIHEADER *hdr,
const ASN1_OCTET_STRING *senderKID);
int ossl_cmp_pkifreetext_push_str(OSSL_CMP_PKIFREETEXT *ft, const char *text);
int ossl_cmp_hdr_push0_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_push1_freeText(OSSL_CMP_PKIHEADER *hdr, ASN1_UTF8STRING *text);
int ossl_cmp_hdr_generalInfo_push0_item(OSSL_CMP_PKIHEADER *hdr,
OSSL_CMP_ITAV *itav);
int ossl_cmp_hdr_generalInfo_push1_items(OSSL_CMP_PKIHEADER *hdr,
STACK_OF(OSSL_CMP_ITAV) *itavs);
const STACK_OF(OSSL_CMP_ITAV) *itavs);
int ossl_cmp_hdr_set_implicitConfirm(OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_check_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
int ossl_cmp_hdr_has_implicitConfirm(const OSSL_CMP_PKIHEADER *hdr);
# define OSSL_CMP_TRANSACTIONID_LENGTH 16
# define OSSL_CMP_SENDERNONCE_LENGTH 16
int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
@@ -860,6 +846,10 @@ int ossl_cmp_hdr_init(OSSL_CMP_CTX *ctx, OSSL_CMP_PKIHEADER *hdr);
# define OSSL_CMP_PKIBODY_POLLREQ 25
# define OSSL_CMP_PKIBODY_POLLREP 26
# define OSSL_CMP_PKIBODY_TYPE_MAX OSSL_CMP_PKIBODY_POLLREP
/* certReqId for the first - and so far only - certificate request */
# define OSSL_CMP_CERTREQID 0
/* sequence id for the first - and so far only - revocation request */
# define OSSL_CMP_REVREQSID 0
const char *ossl_cmp_bodytype_to_string(int type);
int ossl_cmp_msg_set_bodytype(OSSL_CMP_MSG *msg, int type);
int ossl_cmp_msg_get_bodytype(const OSSL_CMP_MSG *msg);
@@ -875,24 +865,26 @@ OSSL_CMP_MSG *ossl_cmp_rr_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
OSSL_CRMF_CERTID *certId, int unprot_err);
OSSL_CMP_MSG *ossl_cmp_pkiconf_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav);
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
STACK_OF(OSSL_CMP_ITAV) *itavs);
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx);
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs);
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
int errorCode,
OSSL_CMP_PKIFREETEXT *errorDetails,
int unprotected);
int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus,
const X509 *cert);
const char *details, int unprotected);
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash);
OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
const char *text);
OSSL_CMP_MSG *ossl_cmp_pollReq_new(OSSL_CMP_CTX *ctx, int crid);
OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
int64_t poll_after);
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid);
OSSL_CRMF_CERTID *ossl_cmp_revrepcontent_get_CertId(OSSL_CMP_REVREPCONTENT *rrep,
int rsid);
OSSL_CMP_POLLREP *
@@ -904,11 +896,6 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crepmsg
X509 *ossl_cmp_certresponse_get1_certificate(EVP_PKEY *privkey,
const OSSL_CMP_CERTRESPONSE *crep);
OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file);
/* BIO definitions */
# define OSSL_d2i_CMP_MSG_bio(bp, p) \
ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new, d2i_OSSL_CMP_MSG, bp, p)
# define OSSL_i2d_CMP_MSG_bio(bp, o) \
ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bp, o)
/* from cmp_protect.c */
ASN1_BIT_STRING *ossl_cmp_calc_protection(const OSSL_CMP_MSG *msg,
@@ -925,4 +912,10 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
ossl_cmp_allow_unprotected_cb_t cb, int cb_arg);
int ossl_cmp_verify_popo(const OSSL_CMP_MSG *msg, int accept_RAVerified);
#endif /* !defined OSSL_CRYPTO_CMP_LOCAL_H */
/* from cmp_client.c */
int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int fail_info,
const char *txt);
int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info,
const char *txt, int errorCode, const char *details);
#endif /* !defined(OSSL_CRYPTO_CMP_LOCAL_H) */
+70 -72
View File
@@ -185,8 +185,8 @@ OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype)
(sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \
|| OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1)
static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
int bodytype)
static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
int bodytype)
{
if (ctx->subjectName != NULL)
return ctx->subjectName;
@@ -205,18 +205,20 @@ static X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, X509 *refcert,
* Create CRMF certificate request message for IR/CR/KUR
* returns a pointer to the OSSL_CRMF_MSG on success, NULL on error
*/
static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype,
int rid, EVP_PKEY *rkey)
static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype, int rid)
{
OSSL_CRMF_MSG *crm = NULL;
X509 *refcert = ctx->oldCert != NULL ? ctx->oldCert : ctx->clCert;
/* refcert defaults to current client cert */
EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
STACK_OF(GENERAL_NAME) *default_sans = NULL;
X509_NAME *subject = determine_subj(ctx, refcert, bodytype);
const X509_NAME *subject = determine_subj(ctx, refcert, bodytype);
int crit = ctx->setSubjectAltNameCritical || subject == NULL;
/* RFC5280: subjectAltName MUST be critical if subject is null */
X509_EXTENSIONS *exts = NULL;
if (rkey == NULL)
rkey = ctx->pkey; /* default is independent of ctx->oldClCert */
if (rkey == NULL
|| (bodytype == OSSL_CMP_PKIBODY_KUR && refcert == NULL)) {
CMPerr(0, CMP_R_INVALID_ARGS);
@@ -300,19 +302,12 @@ static OSSL_CRMF_MSG *crm_new(OSSL_CMP_CTX *ctx, int bodytype,
OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code)
{
EVP_PKEY *rkey;
EVP_PKEY *privkey;
OSSL_CMP_MSG *msg;
OSSL_CRMF_MSG *crm = NULL;
if (!ossl_assert(ctx != NULL))
return NULL;
rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0);
if (rkey == NULL)
return NULL;
privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
if (type != OSSL_CMP_PKIBODY_IR && type != OSSL_CMP_PKIBODY_CR
&& type != OSSL_CMP_PKIBODY_KUR && type != OSSL_CMP_PKIBODY_P10CR) {
CMPerr(0, CMP_R_INVALID_ARGS);
@@ -329,15 +324,19 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code)
/* body */
/* For P10CR the content has already been set in OSSL_CMP_MSG_create */
if (type != OSSL_CMP_PKIBODY_P10CR) {
EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
if (privkey == NULL)
privkey = ctx->pkey; /* default is independent of ctx->oldCert */
if (ctx->popoMethod == OSSL_CRMF_POPO_SIGNATURE && privkey == NULL) {
CMPerr(0, CMP_R_MISSING_PRIVATE_KEY);
goto err;
}
if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID, rkey)) == NULL
|| !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest,
ctx->popoMethod)
/* value.ir is same for cr and kur */
|| !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm))
if ((crm = crm_new(ctx, type, OSSL_CMP_CERTREQID)) == NULL
|| !OSSL_CRMF_MSG_create_popo(crm, privkey, ctx->digest,
ctx->popoMethod)
/* value.ir is same for cr and kur */
|| !sk_OSSL_CRMF_MSG_push(msg->body->value.ir, crm))
goto err;
crm = NULL;
/* TODO: here optional 2nd certreqmsg could be pushed to the stack */
@@ -349,7 +348,8 @@ OSSL_CMP_MSG *ossl_cmp_certReq_new(OSSL_CMP_CTX *ctx, int type, int err_code)
return msg;
err:
CMPerr(0, err_code);
if (err_code != 0)
CMPerr(0, err_code);
OSSL_CRMF_MSG_free(crm);
OSSL_CMP_MSG_free(msg);
return NULL;
@@ -385,7 +385,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype,
|| !ASN1_INTEGER_set(resp->certReqId, certReqId))
goto err;
status = ossl_cmp_pkisi_get_pkistatus(resp->status);
status = ossl_cmp_pkisi_get_status(resp->status);
if (status != OSSL_CMP_PKISTATUS_rejection
&& status != OSSL_CMP_PKISTATUS_waiting && cert != NULL) {
if (encrypted) {
@@ -416,7 +416,7 @@ OSSL_CMP_MSG *ossl_cmp_certRep_new(OSSL_CMP_CTX *ctx, int bodytype,
goto err;
if (!unprotectedErrors
|| ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection)
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -511,7 +511,7 @@ OSSL_CMP_MSG *ossl_cmp_rp_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
}
if (!unprot_err
|| ossl_cmp_pkisi_get_pkistatus(si) != OSSL_CMP_PKISTATUS_rejection)
|| ossl_cmp_pkisi_get_status(si) != OSSL_CMP_PKISTATUS_rejection)
if (!ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -560,7 +560,7 @@ int ossl_cmp_msg_gen_push0_ITAV(OSSL_CMP_MSG *msg, OSSL_CMP_ITAV *itav)
}
int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
STACK_OF(OSSL_CMP_ITAV) *itavs)
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
int i;
OSSL_CMP_ITAV *itav = NULL;
@@ -583,7 +583,9 @@ int ossl_cmp_msg_gen_push1_ITAVs(OSSL_CMP_MSG *msg,
* Creates a new General Message/Response with an empty itav stack
* returns a pointer to the PKIMessage on success, NULL on error
*/
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs,
int body_type, int err_code)
{
OSSL_CMP_MSG *msg = NULL;
@@ -594,7 +596,7 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
return NULL;
if (ctx->genm_ITAVs != NULL
&& !ossl_cmp_msg_gen_push1_ITAVs(msg, ctx->genm_ITAVs))
&& !ossl_cmp_msg_gen_push1_ITAVs(msg, itavs))
goto err;
if (!ossl_cmp_msg_protect(ctx, msg))
@@ -610,20 +612,23 @@ static OSSL_CMP_MSG *gen_new(OSSL_CMP_CTX *ctx, int body_type, int err_code)
OSSL_CMP_MSG *ossl_cmp_genm_new(OSSL_CMP_CTX *ctx)
{
return gen_new(ctx, OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
return gen_new(ctx, ctx->genm_ITAVs,
OSSL_CMP_PKIBODY_GENM, CMP_R_ERROR_CREATING_GENM);
}
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx)
OSSL_CMP_MSG *ossl_cmp_genp_new(OSSL_CMP_CTX *ctx,
const STACK_OF(OSSL_CMP_ITAV) *itavs)
{
return gen_new(ctx, OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
return gen_new(ctx, itavs,
OSSL_CMP_PKIBODY_GENP, CMP_R_ERROR_CREATING_GENP);
}
OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
int errorCode,
OSSL_CMP_PKIFREETEXT *errorDetails,
int unprotected)
const char *details, int unprotected)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKIFREETEXT *ft;
if (!ossl_assert(ctx != NULL && si != NULL))
return NULL;
@@ -641,11 +646,13 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
if (!ASN1_INTEGER_set(msg->body->value.error->errorCode, errorCode))
goto err;
}
if (errorDetails != NULL)
if ((msg->body->value.error->errorDetails =
sk_ASN1_UTF8STRING_deep_copy(errorDetails, ASN1_STRING_dup,
ASN1_STRING_free)) == NULL)
if (details != NULL) {
if ((ft = sk_ASN1_UTF8STRING_new_null()) == NULL)
goto err;
msg->body->value.error->errorDetails = ft;
if (!ossl_cmp_sk_ASN1_UTF8STRING_push_str(ft, details))
goto err;
}
if (!unprotected && !ossl_cmp_msg_protect(ctx, msg))
goto err;
@@ -658,44 +665,18 @@ OSSL_CMP_MSG *ossl_cmp_error_new(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si,
}
/*
* OSSL_CMP_CERTSTATUS_set_certHash() calculates a hash of the certificate,
* using the same hash algorithm as is used to create and verify the
* certificate signature, and places the hash into the certHash field of a
* OSSL_CMP_CERTSTATUS structure. This is used in the certConf message,
* for example, to confirm that the certificate was received successfully.
* Set the certHash field of a OSSL_CMP_CERTSTATUS structure.
* This is used in the certConf message, for example,
* to confirm that the certificate was received successfully.
*/
int ossl_cmp_certstatus_set_certHash(OSSL_CMP_CERTSTATUS *certStatus,
const X509 *cert)
int ossl_cmp_certstatus_set0_certHash(OSSL_CMP_CERTSTATUS *certStatus,
ASN1_OCTET_STRING *hash)
{
unsigned int len;
unsigned char hash[EVP_MAX_MD_SIZE];
int md_NID;
const EVP_MD *md = NULL;
if (!ossl_assert(certStatus != NULL && cert != NULL))
if (!ossl_assert(certStatus != NULL))
return 0;
/*-
* select hash algorithm, as stated in Appendix F. Compilable ASN.1 defs:
* the hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature
*/
if (OBJ_find_sigid_algs(X509_get_signature_nid(cert), &md_NID, NULL)
&& (md = EVP_get_digestbynid(md_NID)) != NULL) {
if (!X509_digest(cert, md, hash, &len))
goto err;
if (!ossl_cmp_asn1_octet_string_set1_bytes(&certStatus->certHash, hash,
len))
goto err;
} else {
CMPerr(0, CMP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
ASN1_OCTET_STRING_free(certStatus->certHash);
certStatus->certHash = hash;
return 1;
err:
CMPerr(0, CMP_R_ERROR_SETTING_CERTHASH);
return 0;
}
/*
@@ -707,6 +688,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *certStatus = NULL;
ASN1_OCTET_STRING *certHash = NULL;
OSSL_CMP_PKISI *sinfo;
if (!ossl_assert(ctx != NULL && ctx->newCert != NULL))
@@ -732,8 +714,12 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
* the hash of the certificate, using the same hash algorithm
* as is used to create and verify the certificate signature
*/
if (!ossl_cmp_certstatus_set_certHash(certStatus, ctx->newCert))
if ((certHash = X509_digest_sig(ctx->newCert)) == NULL)
goto err;
if (!ossl_cmp_certstatus_set0_certHash(certStatus, certHash))
goto err;
certHash = NULL;
/*
* For any particular CertStatus, omission of the statusInfo field
* indicates ACCEPTANCE of the specified certificate. Alternatively,
@@ -742,8 +728,8 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
* the CA/RA.
*/
sinfo = fail_info != 0 ?
ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
ossl_cmp_statusinfo_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection, fail_info, text) :
OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_accepted, 0, text);
if (sinfo == NULL)
goto err;
certStatus->statusInfo = sinfo;
@@ -756,6 +742,7 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int fail_info,
err:
CMPerr(0, CMP_R_ERROR_CREATING_CERTCONF);
OSSL_CMP_MSG_free(msg);
ASN1_OCTET_STRING_free(certHash);
return NULL;
}
@@ -827,7 +814,7 @@ OSSL_CMP_MSG *ossl_cmp_pollRep_new(OSSL_CMP_CTX *ctx, int crid,
* returns NULL on error
*/
OSSL_CMP_PKISI *
ossl_cmp_revrepcontent_get_pkistatusinfo(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
ossl_cmp_revrepcontent_get_pkisi(OSSL_CMP_REVREPCONTENT *rrep, int rsid)
{
OSSL_CMP_PKISI *status;
@@ -990,7 +977,18 @@ OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file)
if ((bio = BIO_new_file(file, "rb")) == NULL)
return NULL;
msg = OSSL_d2i_CMP_MSG_bio(bio, NULL);
msg = d2i_OSSL_CMP_MSG_bio(bio, NULL);
BIO_free(bio);
return msg;
}
OSSL_CMP_MSG *d2i_OSSL_CMP_MSG_bio(BIO *bio, OSSL_CMP_MSG **msg)
{
return ASN1_d2i_bio_of(OSSL_CMP_MSG, OSSL_CMP_MSG_new,
d2i_OSSL_CMP_MSG, bio, msg);
}
int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg)
{
return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg);
}
+14 -1
View File
@@ -286,6 +286,8 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
* to section 5.1.1
*/
subjKeyIDStr = X509_get0_subject_key_id(ctx->clCert);
if (subjKeyIDStr == NULL)
subjKeyIDStr = ctx->referenceValue; /* fallback */
if (subjKeyIDStr != NULL
&& !ossl_cmp_hdr_set1_senderKID(msg->header, subjKeyIDStr))
goto err;
@@ -306,7 +308,18 @@ int ossl_cmp_msg_protect(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg)
}
}
return 1;
/*
* As required by RFC 4210 section 5.1.1., if the sender name is not known
* to the client it set to NULL-DN. In this case for identification at least
* the senderKID must be set, where we took the referenceValue as fallback.
*/
if (ossl_cmp_general_name_is_NULL_DN(msg->header->sender)
&& msg->header->senderKID == NULL)
CMPerr(0, CMP_R_MISSING_SENDER_IDENTIFICATION);
else
return 1;
err:
CMPerr(0, CMP_R_ERROR_PROTECTING_MESSAGE);
return 0;
+619
View File
@@ -0,0 +1,619 @@
/*
* Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright Nokia 2007-2019
* Copyright Siemens AG 2015-2019
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* general CMP server functions */
#include <openssl/asn1t.h>
#include "cmp_local.h"
/* explicit #includes not strictly needed since implied by the above: */
#include <openssl/cmp.h>
#include <openssl/err.h>
/* the context for the generic CMP server */
struct ossl_cmp_srv_ctx_st
{
OSSL_CMP_CTX *ctx; /* Client CMP context, partly reused for srv */
void *custom_ctx; /* pointer to specific server context */
OSSL_CMP_SRV_cert_request_cb_t process_cert_request;
OSSL_CMP_SRV_rr_cb_t process_rr;
OSSL_CMP_SRV_genm_cb_t process_genm;
OSSL_CMP_SRV_error_cb_t process_error;
OSSL_CMP_SRV_certConf_cb_t process_certConf;
OSSL_CMP_SRV_pollReq_cb_t process_pollReq;
int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */
int acceptUnprotected; /* Accept requests with no/invalid prot. */
int acceptRAVerified; /* Accept ir/cr/kur with POPO RAVerified */
int grantImplicitConfirm; /* Grant implicit confirmation if requested */
}; /* OSSL_CMP_SRV_CTX */
void OSSL_CMP_SRV_CTX_free(OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL)
return;
OSSL_CMP_CTX_free(srv_ctx->ctx);
OPENSSL_free(srv_ctx);
}
OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(void)
{
OSSL_CMP_SRV_CTX *ctx = OPENSSL_zalloc(sizeof(OSSL_CMP_SRV_CTX));
if (ctx == NULL)
goto err;
if ((ctx->ctx = OSSL_CMP_CTX_new()) == NULL)
goto err;
/* all other elements are initialized to 0 or NULL, respectively */
return ctx;
err:
OSSL_CMP_SRV_CTX_free(ctx);
return NULL;
}
int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx,
OSSL_CMP_SRV_cert_request_cb_t process_cert_request,
OSSL_CMP_SRV_rr_cb_t process_rr,
OSSL_CMP_SRV_genm_cb_t process_genm,
OSSL_CMP_SRV_error_cb_t process_error,
OSSL_CMP_SRV_certConf_cb_t process_certConf,
OSSL_CMP_SRV_pollReq_cb_t process_pollReq)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->custom_ctx = custom_ctx;
srv_ctx->process_cert_request = process_cert_request;
srv_ctx->process_rr = process_rr;
srv_ctx->process_genm = process_genm;
srv_ctx->process_error = process_error;
srv_ctx->process_certConf = process_certConf;
srv_ctx->process_pollReq = process_pollReq;
return 1;
}
OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->ctx;
}
void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return srv_ctx->custom_ctx;
}
int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->sendUnprotectedErrors = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_unprotected(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptUnprotected = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_accept_raverified(OSSL_CMP_SRV_CTX *srv_ctx, int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->acceptRAVerified = val != 0;
return 1;
}
int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx,
int val)
{
if (srv_ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
srv_ctx->grantImplicitConfirm = val != 0;
return 1;
}
/*
* Processes an ir/cr/p10cr/kur and returns a certification response.
* Only handles the first certification request contained in req
* returns an ip/cp/kup on success and NULL on error
*/
static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_PKISI *si = NULL;
X509 *certOut = NULL;
STACK_OF(X509) *chainOut = NULL, *caPubs = NULL;
const OSSL_CRMF_MSG *crm = NULL;
const X509_REQ *p10cr = NULL;
int bodytype;
int certReqId;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
switch (ossl_cmp_msg_get_bodytype(req)) {
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_CR:
bodytype = OSSL_CMP_PKIBODY_CP;
break;
case OSSL_CMP_PKIBODY_IR:
bodytype = OSSL_CMP_PKIBODY_IP;
break;
case OSSL_CMP_PKIBODY_KUR:
bodytype = OSSL_CMP_PKIBODY_KUP;
break;
default:
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
return NULL;
}
if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_P10CR) {
certReqId = OSSL_CMP_CERTREQID;
p10cr = req->body->value.p10cr;
} else {
OSSL_CRMF_MSGS *reqs = req->body->value.ir; /* same for cr and kur */
if (sk_OSSL_CRMF_MSG_num(reqs) != 1) { /* TODO: handle case > 1 */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) {
CMPerr(0, CMP_R_CERTREQMSG_NOT_FOUND);
return NULL;
}
certReqId = OSSL_CRMF_MSG_get_certReqId(crm);
}
if (!ossl_cmp_verify_popo(req, srv_ctx->acceptRAVerified)) {
/* Proof of possession could not be verified */
si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
1 << OSSL_CMP_PKIFAILUREINFO_badPOP,
ERR_reason_error_string(ERR_peek_error()));
if (si == NULL)
return NULL;
} else {
OSSL_CMP_PKIHEADER *hdr = OSSL_CMP_MSG_get0_header(req);
si = srv_ctx->process_cert_request(srv_ctx, req, certReqId, crm, p10cr,
&certOut, &chainOut, &caPubs);
if (si == NULL)
goto err;
/* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */
if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM,
ossl_cmp_hdr_has_implicitConfirm(hdr)
&& srv_ctx->grantImplicitConfirm
/* do not set if polling starts: */
&& certOut != NULL))
goto err;
}
msg = ossl_cmp_certRep_new(srv_ctx->ctx, bodytype, certReqId, si,
certOut, chainOut, caPubs, 0 /* encrypted */,
srv_ctx->sendUnprotectedErrors);
/*
* TODO when implemented in ossl_cmp_certrep_new():
* in case OSSL_CRMF_POPO_KEYENC, set encrypted
*/
if (msg == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_CERTREP);
err:
OSSL_CMP_PKISI_free(si);
X509_free(certOut);
sk_X509_pop_free(chainOut, X509_free);
sk_X509_pop_free(caPubs, X509_free);
return msg;
}
static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_REVDETAILS *details;
OSSL_CRMF_CERTID *certId;
OSSL_CRMF_CERTTEMPLATE *tmpl;
const X509_NAME *issuer;
ASN1_INTEGER *serial;
OSSL_CMP_PKISI *si;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (sk_OSSL_CMP_REVDETAILS_num(req->body->value.rr) != 1) {
/* TODO: handle multiple elements if multiple requests have been sent */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr,
OSSL_CMP_REVREQSID)) == NULL) {
CMPerr(0, CMP_R_ERROR_PROCESSING_MESSAGE);
return NULL;
}
tmpl = details->certDetails;
issuer = OSSL_CRMF_CERTTEMPLATE_get0_issuer(tmpl);
serial = OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(tmpl);
/* here issuer and serial may safely be NULL */
if ((certId = OSSL_CRMF_CERTID_gen(issuer, serial)) == NULL)
return NULL;
if ((si = srv_ctx->process_rr(srv_ctx, req, issuer, serial)) == NULL)
goto err;
if ((msg = ossl_cmp_rp_new(srv_ctx->ctx, si, certId,
srv_ctx->sendUnprotectedErrors)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_RR);
err:
OSSL_CRMF_CERTID_free(certId);
OSSL_CMP_PKISI_free(si);
return msg;
}
/*
* Processes genm and creates a genp message mirroring the contents of the
* incoming message
*/
static OSSL_CMP_MSG *process_genm(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_GENMSGCONTENT *itavs;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
if (!srv_ctx->process_genm(srv_ctx, req, req->body->value.genm, &itavs))
return NULL;
msg = ossl_cmp_genp_new(srv_ctx->ctx, itavs);
sk_OSSL_CMP_ITAV_pop_free(itavs, OSSL_CMP_ITAV_free);
return msg;
}
static OSSL_CMP_MSG *process_error(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_ERRORMSGCONTENT *errorContent;
OSSL_CMP_MSG *msg;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
errorContent = req->body->value.error;
srv_ctx->process_error(srv_ctx, req, errorContent->pKIStatusInfo,
errorContent->errorCode, errorContent->errorDetails);
if ((msg = ossl_cmp_pkiconf_new(srv_ctx->ctx)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
OSSL_CMP_CERTCONFIRMCONTENT *ccc;
int num;
OSSL_CMP_MSG *msg = NULL;
OSSL_CMP_CERTSTATUS *status = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
ctx = srv_ctx->ctx;
ccc = req->body->value.certConf;
num = sk_OSSL_CMP_CERTSTATUS_num(ccc);
if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 1) {
CMPerr(0, CMP_R_ERROR_UNEXPECTED_CERTCONF);
return NULL;
}
if (num == 0) {
ossl_cmp_err(ctx, "certificate rejected by client");
} else {
if (num > 1)
ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored");
status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID);
}
if (status != NULL) {
int certReqId = ossl_cmp_asn1_get_int(status->certReqId);
ASN1_OCTET_STRING *certHash = status->certHash;
OSSL_CMP_PKISI *si = status->statusInfo;
if (!srv_ctx->process_certConf(srv_ctx, req, certReqId, certHash, si))
return NULL; /* reason code may be: CMP_R_CERTHASH_UNMATCHED */
if (si != NULL && ossl_cmp_pkisi_get_status(si)
!= OSSL_CMP_PKISTATUS_accepted) {
int pki_status = ossl_cmp_pkisi_get_status(si);
const char *str = ossl_cmp_PKIStatus_to_string(pki_status);
ossl_cmp_log2(INFO, ctx, "certificate rejected by client %s %s",
str == NULL ? "without" : "with",
str == NULL ? "PKIStatus" : str);
}
}
if ((msg = ossl_cmp_pkiconf_new(ctx)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_PKICONF);
return msg;
}
static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_POLLREQCONTENT *prc;
OSSL_CMP_POLLREQ *pr;
int certReqId;
OSSL_CMP_MSG *certReq;
int64_t check_after = 0;
OSSL_CMP_MSG *msg = NULL;
if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL))
return NULL;
prc = req->body->value.pollReq;
if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) { /* TODO: handle case > 1 */
CMPerr(0, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED);
return NULL;
}
pr = sk_OSSL_CMP_POLLREQ_value(prc, 0);
certReqId = ossl_cmp_asn1_get_int(pr->certReqId);
if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId,
&certReq, &check_after))
return NULL;
if (certReq != NULL) {
msg = process_cert_request(srv_ctx, certReq);
OSSL_CMP_MSG_free(certReq);
} else {
if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId,
check_after)) == NULL)
CMPerr(0, CMP_R_ERROR_CREATING_POLLREP);
}
return msg;
}
/*
* Determine whether missing/invalid protection of request message is allowed.
* Return 1 on acceptance, 0 on rejection, or -1 on (internal) error.
*/
static int unprotected_exception(const OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *req,
int invalid_protection,
int accept_unprotected_requests)
{
if (!ossl_assert(ctx != NULL && req != NULL))
return -1;
if (accept_unprotected_requests) {
ossl_cmp_log1(WARN, ctx, "ignoring %s protection of request message",
invalid_protection ? "invalid" : "missing");
return 1;
}
if (ossl_cmp_msg_get_bodytype(req) == OSSL_CMP_PKIBODY_ERROR
&& OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_UNPROTECTED_ERRORS) == 1) {
ossl_cmp_warn(ctx, "ignoring missing protection of error message");
return 1;
}
return 0;
}
/*
* returns created message and NULL on internal error
*/
OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_CTX *ctx;
OSSL_CMP_PKIHEADER *hdr;
int req_type, rsp_type;
OSSL_CMP_MSG *rsp = NULL;
if (srv_ctx == NULL || srv_ctx->ctx == NULL
|| req == NULL || req->body == NULL
|| (hdr = OSSL_CMP_MSG_get0_header(req)) == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
ctx = srv_ctx->ctx;
if (hdr->sender->type != GEN_DIRNAME) {
CMPerr(0, CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED);
goto err;
}
if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName))
goto err;
req_type = ossl_cmp_msg_get_bodytype(req);
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
case OSSL_CMP_PKIBODY_RR:
case OSSL_CMP_PKIBODY_GENM:
case OSSL_CMP_PKIBODY_ERROR:
if (ctx->transactionID != NULL) {
char *tid;
tid = OPENSSL_buf2hexstr(ctx->transactionID->data,
ctx->transactionID->length);
ossl_cmp_log1(WARN, ctx,
"Assuming that last transaction with ID=%s got aborted",
tid);
OPENSSL_free(tid);
}
/* start of a new transaction, set transactionID and senderNonce */
if (!OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID)
|| !ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce))
goto err;
break;
default:
/* transactionID should be already initialized */
if (ctx->transactionID == NULL) {
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
/* ignore any (extra) error in next two function calls: */
(void)OSSL_CMP_CTX_set1_transactionID(ctx, hdr->transactionID);
(void)ossl_cmp_ctx_set1_recipNonce(ctx, hdr->senderNonce);
goto err;
}
}
if (ossl_cmp_msg_check_received(ctx, req, unprotected_exception,
srv_ctx->acceptUnprotected) < 0)
goto err;
switch (req_type) {
case OSSL_CMP_PKIBODY_IR:
case OSSL_CMP_PKIBODY_CR:
case OSSL_CMP_PKIBODY_P10CR:
case OSSL_CMP_PKIBODY_KUR:
if (srv_ctx->process_cert_request == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_cert_request(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_RR:
if (srv_ctx->process_rr == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_rr(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_GENM:
if (srv_ctx->process_genm == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_genm(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_ERROR:
if (srv_ctx->process_error == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_error(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_CERTCONF:
if (srv_ctx->process_certConf == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_certConf(srv_ctx, req);
break;
case OSSL_CMP_PKIBODY_POLLREQ:
if (srv_ctx->process_pollReq == NULL)
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
else
rsp = process_pollReq(srv_ctx, req);
break;
default:
/* TODO possibly support further request message types */
CMPerr(0, CMP_R_UNEXPECTED_PKIBODY);
}
err:
if (rsp == NULL) {
/* on error, try to respond with CMP error message to client */
const char *data = NULL;
int flags = 0;
unsigned long err = ERR_peek_error_data(&data, &flags);
int fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_badRequest;
/* TODO fail_info could be more specific */
OSSL_CMP_PKISI *si = NULL;
if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_rejection,
fail_info, NULL)) == NULL)
return 0;
if (err != 0 && (flags & ERR_TXT_STRING) != 0)
data = ERR_reason_error_string(err);
rsp = ossl_cmp_error_new(srv_ctx->ctx, si,
err != 0 ? ERR_GET_REASON(err) : -1,
data, srv_ctx->sendUnprotectedErrors);
OSSL_CMP_PKISI_free(si);
}
/* possibly close the transaction */
rsp_type =
rsp != NULL ? ossl_cmp_msg_get_bodytype(rsp) : OSSL_CMP_PKIBODY_ERROR;
switch (rsp_type) {
case OSSL_CMP_PKIBODY_IP:
case OSSL_CMP_PKIBODY_CP:
case OSSL_CMP_PKIBODY_KUP:
case OSSL_CMP_PKIBODY_RP:
if (OSSL_CMP_CTX_get_option(ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM) == 0)
break;
/* fall through */
case OSSL_CMP_PKIBODY_PKICONF:
case OSSL_CMP_PKIBODY_GENP:
case OSSL_CMP_PKIBODY_ERROR:
/* TODO possibly support further terminating response message types */
(void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); /* ignore any error */
default: /* not closing transaction in other cases */
break;
}
return rsp;
}
/*
* Server interface that may substitute OSSL_CMP_MSG_http_perform at the client.
* The OSSL_CMP_SRV_CTX must be set as client_ctx->transfer_cb_arg.
* returns received message on success, else NULL and pushes an element on the
* error stack.
*/
OSSL_CMP_MSG * OSSL_CMP_CTX_server_perform(OSSL_CMP_CTX *client_ctx,
const OSSL_CMP_MSG *req)
{
OSSL_CMP_SRV_CTX *srv_ctx = NULL;
if (client_ctx == NULL || req == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return 0;
}
if ((srv_ctx = OSSL_CMP_CTX_get_transfer_cb_arg(client_ctx)) == NULL) {
CMPerr(0, CMP_R_TRANSFER_ERROR);
return 0;
}
return OSSL_CMP_SRV_process_request(srv_ctx, req);
}
+56 -44
View File
@@ -28,17 +28,13 @@
/* CMP functions related to PKIStatus */
int ossl_cmp_pkisi_get_pkistatus(const OSSL_CMP_PKISI *si)
int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si)
{
if (!ossl_assert(si != NULL && si->status != NULL))
return -1;
return ossl_cmp_asn1_get_int(si->status);
}
/*
* return the declared identifier and a short explanation for the PKIStatus
* value as specified in RFC4210, Appendix F.
*/
const char *ossl_cmp_PKIStatus_to_string(int status)
{
switch (status) {
@@ -67,27 +63,19 @@ const char *ossl_cmp_PKIStatus_to_string(int status)
}
}
/*
* returns a pointer to the statusString contained in a PKIStatusInfo
* returns NULL on error
*/
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusstring(const OSSL_CMP_PKISI *si)
OSSL_CMP_PKIFREETEXT *ossl_cmp_pkisi_get0_statusString(const OSSL_CMP_PKISI *si)
{
if (!ossl_assert(si != NULL))
return NULL;
return si->statusString;
}
/*
* returns the FailureInfo bits of the given PKIStatusInfo
* returns -1 on error
*/
int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si)
{
int i;
int res = 0;
if (!ossl_assert(si != NULL && si->failInfo != NULL))
if (!ossl_assert(si != NULL))
return -1;
for (i = 0; i <= OSSL_CMP_PKIFAILUREINFO_MAX; i++)
if (ASN1_BIT_STRING_get_bit(si->failInfo, i))
@@ -95,12 +83,9 @@ int ossl_cmp_pkisi_get_pkifailureinfo(const OSSL_CMP_PKISI *si)
return res;
}
/*
* internal function
/*-
* convert PKIFailureInfo number to human-readable string
*
* returns pointer to static string
* returns NULL on error
* returns pointer to static string, or NULL on error
*/
static const char *CMP_PKIFAILUREINFO_to_string(int number)
{
@@ -164,11 +149,7 @@ static const char *CMP_PKIFAILUREINFO_to_string(int number)
}
}
/*
* checks PKIFailureInfo bits in a given PKIStatusInfo
* returns 1 if a given bit is set, 0 if not, -1 on error
*/
int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index)
int ossl_cmp_pkisi_check_pkifailureinfo(const OSSL_CMP_PKISI *si, int bit_index)
{
if (!ossl_assert(si != NULL && si->failInfo != NULL))
return -1;
@@ -180,16 +161,17 @@ int ossl_cmp_pkisi_pkifailureinfo_check(const OSSL_CMP_PKISI *si, int bit_index)
return ASN1_BIT_STRING_get_bit(si->failInfo, bit_index);
}
/*
/*-
* place human-readable error string created from PKIStatusInfo in given buffer
* returns pointer to the same buffer containing the string, or NULL on error
*/
char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
size_t bufsize)
static
char *snprint_PKIStatusInfo_parts(int status, int fail_info,
const OSSL_CMP_PKIFREETEXT *status_strings,
char *buf, size_t bufsize)
{
int status, failure, fail_info;
int failure;
const char *status_string, *failure_string;
OSSL_CMP_PKIFREETEXT *status_strings;
ASN1_UTF8STRING *text;
int i;
int printed_chars;
@@ -197,22 +179,22 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
int n_status_strings;
char *write_ptr = buf;
#define ADVANCE_BUFFER \
if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
return NULL; \
write_ptr += printed_chars; \
bufsize -= printed_chars;
if (ctx == NULL
|| buf == NULL
|| (status = OSSL_CMP_CTX_get_status(ctx)) < 0
if (buf == NULL
|| status < 0
|| (status_string = ossl_cmp_PKIStatus_to_string(status)) == NULL)
return NULL;
#define ADVANCE_BUFFER \
if (printed_chars < 0 || (size_t)printed_chars >= bufsize) \
return NULL; \
write_ptr += printed_chars; \
bufsize -= printed_chars;
printed_chars = BIO_snprintf(write_ptr, bufsize, "%s", status_string);
ADVANCE_BUFFER;
/* failInfo is optional and may be empty */
if ((fail_info = OSSL_CMP_CTX_get_failInfoCode(ctx)) > 0) {
if (fail_info != 0) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "; PKIFailureInfo: ");
ADVANCE_BUFFER;
for (failure = 0; failure <= OSSL_CMP_PKIFAILUREINFO_MAX; failure++) {
@@ -220,7 +202,7 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
failure_string = CMP_PKIFAILUREINFO_to_string(failure);
if (failure_string != NULL) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "%s%s",
failure > 0 ? ", " : "",
failinfo_found ? ", " : "",
failure_string);
ADVANCE_BUFFER;
failinfo_found = 1;
@@ -235,7 +217,6 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
}
/* statusString sequence is optional and may be empty */
status_strings = OSSL_CMP_CTX_get0_statusString(ctx);
n_status_strings = sk_ASN1_UTF8STRING_num(status_strings);
if (n_status_strings > 0) {
printed_chars = BIO_snprintf(write_ptr, bufsize, "; StatusString%s: ",
@@ -253,13 +234,44 @@ char *OSSL_CMP_CTX_snprint_PKIStatus(OSSL_CMP_CTX *ctx, char *buf,
return buf;
}
/*
char *OSSL_CMP_snprint_PKIStatusInfo(const OSSL_CMP_PKISI *statusInfo,
char *buf, size_t bufsize)
{
int failure_info;
if (statusInfo == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
failure_info = ossl_cmp_pkisi_get_pkifailureinfo(statusInfo);
return snprint_PKIStatusInfo_parts(ASN1_INTEGER_get(statusInfo->status),
failure_info,
statusInfo->statusString, buf, bufsize);
}
char *OSSL_CMP_CTX_snprint_PKIStatus(const OSSL_CMP_CTX *ctx, char *buf,
size_t bufsize)
{
if (ctx == NULL) {
CMPerr(0, CMP_R_NULL_ARGUMENT);
return NULL;
}
return snprint_PKIStatusInfo_parts(OSSL_CMP_CTX_get_status(ctx),
OSSL_CMP_CTX_get_failInfoCode(ctx),
OSSL_CMP_CTX_get0_statusString(ctx),
buf, bufsize);
}
/*-
* Creates a new PKIStatusInfo structure and fills it in
* returns a pointer to the structure on success, NULL on error
* note: strongly overlaps with TS_RESP_CTX_set_status_info()
* and TS_RESP_CTX_add_failure_info() in ../ts/ts_rsp_sign.c
*/
OSSL_CMP_PKISI *ossl_cmp_statusinfo_new(int status, int fail_info,
OSSL_CMP_PKISI *OSSL_CMP_STATUSINFO_new(int status, int fail_info,
const char *text)
{
OSSL_CMP_PKISI *si = OSSL_CMP_PKISI_new();
+21 -1
View File
@@ -144,7 +144,7 @@ int OSSL_CMP_print_to_bio(BIO *bio, const char *component, const char *file,
#define ERR_PRINT_BUF_SIZE 4096
/* this is similar to ERR_print_errors_cb, but uses the CMP-specific cb type */
void OSSL_CMP_print_errors_cb(OSSL_cmp_log_cb_t log_fn)
void OSSL_CMP_print_errors_cb(OSSL_CMP_log_cb_t log_fn)
{
unsigned long err;
char msg[ERR_PRINT_BUF_SIZE];
@@ -320,6 +320,26 @@ STACK_OF(X509) *ossl_cmp_build_cert_chain(STACK_OF(X509) *certs, X509 *cert)
return result;
}
int ossl_cmp_sk_ASN1_UTF8STRING_push_str(STACK_OF(ASN1_UTF8STRING) *sk,
const char *text)
{
ASN1_UTF8STRING *utf8string;
if (!ossl_assert(sk != NULL && text != NULL))
return 0;
if ((utf8string = ASN1_UTF8STRING_new()) == NULL)
return 0;
if (!ASN1_STRING_set(utf8string, text, -1))
goto err;
if (!sk_ASN1_UTF8STRING_push(sk, utf8string))
goto err;
return 1;
err:
ASN1_UTF8STRING_free(utf8string);
return 0;
}
int ossl_cmp_asn1_octet_string_set1(ASN1_OCTET_STRING **tgt,
const ASN1_OCTET_STRING *src)
{
+107 -67
View File
@@ -167,6 +167,8 @@ int OSSL_CMP_validate_cert_path(OSSL_CMP_CTX *ctx, X509_STORE *trusted_store,
CMPerr(0, CMP_R_POTENTIALLY_INVALID_CERTIFICATE);
err:
/* directly output any fresh errors, needed for check_msg_find_cert() */
OSSL_CMP_CTX_print_errors(ctx);
X509_STORE_CTX_free(csc);
return valid;
}
@@ -250,17 +252,22 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx,
const OSSL_CMP_MSG *msg)
{
X509_STORE *ts = ctx->trusted;
char *sub, *iss;
int self_issued = X509_check_issued(cert, cert) == X509_V_OK;
char *str;
X509_VERIFY_PARAM *vpm = ts != NULL ? X509_STORE_get0_param(ts) : NULL;
int time_cmp;
ossl_cmp_log2(INFO, ctx, " considering %s %s with..", desc1, desc2);
if ((sub = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " subject = %s", sub);
if ((iss = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " issuer = %s", iss);
OPENSSL_free(iss);
OPENSSL_free(sub);
ossl_cmp_log3(INFO, ctx, " considering %s%s %s with..",
self_issued ? "self-issued ": "", desc1, desc2);
if ((str = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0)) != NULL)
ossl_cmp_log1(INFO, ctx, " subject = %s", str);
OPENSSL_free(str);
if (!self_issued) {
str = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
if (str != NULL)
ossl_cmp_log1(INFO, ctx, " issuer = %s", str);
OPENSSL_free(str);
}
if (already_checked(cert, already_checked1)
|| already_checked(cert, already_checked2)) {
@@ -284,7 +291,7 @@ static int cert_acceptable(OSSL_CMP_CTX *ctx,
if (!check_kid(ctx, cert, msg->header->senderKID))
return 0;
/* acceptable also if there is no senderKID in msg header */
ossl_cmp_info(ctx, " cert is acceptable");
ossl_cmp_info(ctx, " cert seems acceptable");
return 1;
}
@@ -295,38 +302,49 @@ static int check_msg_valid_cert(OSSL_CMP_CTX *ctx, X509_STORE *store,
ossl_cmp_warn(ctx, "msg signature verification failed");
return 0;
}
if (!OSSL_CMP_validate_cert_path(ctx, store, scrt)) {
ossl_cmp_warn(ctx, "cert path validation failed");
return 0;
}
return 1;
if (OSSL_CMP_validate_cert_path(ctx, store, scrt))
return 1;
ossl_cmp_warn(ctx,
"msg signature validates but cert path validation failed");
return 0;
}
/*
* Exceptional handling for 3GPP TS 33.310 [3G/LTE Network Domain Security
* (NDS); Authentication Framework (AF)], only to use for IP and if the ctx
* option is explicitly set: use self-issued certificates from extraCerts as
* trust anchor to validate sender cert and msg -
* (NDS); Authentication Framework (AF)], only to use for IP messages
* and if the ctx option is explicitly set: use self-issued certificates
* from extraCerts as trust anchor to validate sender cert and msg -
* provided it also can validate the newly enrolled certificate
*/
static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt,
const OSSL_CMP_MSG *msg)
{
int valid = 0;
X509_STORE *store = X509_STORE_new();
X509_STORE *store;
if (store != NULL /* store does not include CRLs */
&& ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
1 /* self-issued only */))
valid = check_msg_valid_cert(ctx, store, scrt, msg);
if (valid) {
if (!ctx->permitTAInExtraCertsForIR)
return 0;
if ((store = X509_STORE_new()) == NULL
|| !ossl_cmp_X509_STORE_add1_certs(store, msg->extraCerts,
1 /* self-issued only */))
goto err;
/* store does not include CRLs */
valid = OSSL_CMP_validate_cert_path(ctx, store, scrt);
if (!valid) {
ossl_cmp_warn(ctx,
"also exceptional 3GPP mode cert path validation failed");
} else {
/*
* verify that the newly enrolled certificate (which is assumed to have
* rid == 0) can also be validated with the same trusted store
* verify that the newly enrolled certificate (which assumed rid ==
* OSSL_CMP_CERTREQID) can also be validated with the same trusted store
*/
EVP_PKEY *privkey = OSSL_CMP_CTX_get0_newPkey(ctx, 1);
OSSL_CMP_CERTRESPONSE *crep =
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip, 0);
ossl_cmp_certrepmessage_get0_certresponse(msg->body->value.ip,
OSSL_CMP_CERTREQID);
X509 *newcrt = ossl_cmp_certresponse_get1_certificate(privkey, crep);
/*
* maybe better use get_cert_status() from cmp_client.c, which catches
@@ -335,6 +353,8 @@ static int check_msg_valid_cert_3gpp(OSSL_CMP_CTX *ctx, X509 *scrt,
valid = OSSL_CMP_validate_cert_path(ctx, store, newcrt);
X509_free(newcrt);
}
err:
X509_STORE_free(store);
return valid;
}
@@ -393,8 +413,13 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
{
int ret = 0;
if (mode_3gpp
&& ((!ctx->permitTAInExtraCertsForIR
|| ossl_cmp_msg_get_bodytype(msg) != OSSL_CMP_PKIBODY_IP)))
return 0;
ossl_cmp_info(ctx,
mode_3gpp ? "failed; trying now 3GPP mode trusting extraCerts"
mode_3gpp ? "normal mode failed; trying now 3GPP mode trusting extraCerts"
: "trying first normal mode using trust store");
if (check_msg_with_certs(ctx, msg->extraCerts, "extraCerts",
NULL, NULL, msg, mode_3gpp))
@@ -418,6 +443,12 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
return ret;
}
static int no_log_cb(const char *func, const char *file, int line,
OSSL_CMP_severity level, const char *msg)
{
return 1;
}
/* verify message signature with any acceptable and valid candidate cert */
static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
{
@@ -426,7 +457,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
char *sname = NULL;
char *skid_str = NULL;
const ASN1_OCTET_STRING *skid = msg->header->senderKID;
OSSL_cmp_log_cb_t backup_log_cb = ctx->log_cb;
OSSL_CMP_log_cb_t backup_log_cb = ctx->log_cb;
int res = 0;
if (sender == NULL || msg->body == NULL)
@@ -436,49 +467,52 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
return 0;
}
/* dump any hitherto errors to avoid confusion when printing further ones */
OSSL_CMP_CTX_print_errors(ctx);
/*
* try first cached scrt, used successfully earlier in same transaction,
* for validating this and any further msgs where extraCerts may be left out
*/
(void)ERR_set_mark();
if (scrt != NULL
&& cert_acceptable(ctx, "previously validated", "sender cert", scrt,
NULL, NULL, msg)
&& (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg)
if (scrt != NULL) {
(void)ERR_set_mark();
ossl_cmp_info(ctx,
"trying to verify msg signature with previously validated cert");
if (cert_acceptable(ctx, "previously validated", "sender cert", scrt,
NULL, NULL, msg)
&& (check_msg_valid_cert(ctx, ctx->trusted, scrt, msg)
|| check_msg_valid_cert_3gpp(ctx, scrt, msg))) {
(void)ERR_pop_to_mark();
return 1;
}
(void)ERR_pop_to_mark();
return 1;
/* cached sender cert has shown to be no more successfully usable */
(void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
}
(void)ERR_pop_to_mark();
/* release any cached sender cert that proved no more successfully usable */
(void)ossl_cmp_ctx_set0_validatedSrvCert(ctx, NULL);
/* enable clearing irrelevant errors in attempts to validate sender certs */
(void)ERR_set_mark();
ctx->log_cb = NULL; /* temporarily disable logging diagnostic info */
if (check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
|| check_msg_all_certs(ctx, msg, 1 /* 3gpp */)) {
/* discard any diagnostic info on trying to use certs */
ctx->log_cb = backup_log_cb; /* restore any logging */
ctx->log_cb = no_log_cb; /* temporarily disable logging */
res = check_msg_all_certs(ctx, msg, 0 /* using ctx->trusted */)
|| check_msg_all_certs(ctx, msg, 1 /* 3gpp */);
ctx->log_cb = backup_log_cb;
if (res) {
/* discard any diagnostic information on trying to use certs */
(void)ERR_pop_to_mark();
res = 1;
goto end;
}
/* failed finding a sender cert that verifies the message signature */
ctx->log_cb = backup_log_cb; /* restore any logging */
(void)ERR_clear_last_mark();
sname = X509_NAME_oneline(sender->d.directoryName, NULL, 0);
skid_str = skid == NULL ? NULL
: OPENSSL_buf2hexstr(skid->data, skid->length);
if (ctx->log_cb != NULL) {
ossl_cmp_info(ctx, "verifying msg signature with valid cert that..");
ossl_cmp_info(ctx, "trying to verify msg signature with a valid cert that..");
if (sname != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg sender name = %s", sname);
ossl_cmp_log1(INFO, ctx, "matches msg sender = %s", sname);
if (skid_str != NULL)
ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
ossl_cmp_log1(INFO, ctx, "matches msg senderKID = %s", skid_str);
else
ossl_cmp_info(ctx, "while msg header does not contain senderKID");
/* re-do the above checks (just) for adding diagnostic information */
@@ -543,6 +577,11 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
switch (nid) {
/* 5.1.3.1. Shared Secret Information */
case NID_id_PasswordBasedMAC:
if (ctx->secretValue == 0) {
CMPerr(0, CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE);
break;
}
if (verify_PBMAC(msg, ctx->secretValue)) {
/*
* RFC 4210, 5.3.2: 'Note that if the PKI Message Protection is
@@ -633,8 +672,8 @@ int OSSL_CMP_validate_msg(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg)
*
* Ensures that:
* it has a valid body type
* its protection is valid or absent (allowed only if callback function is
* present and function yields non-zero result using also supplied argument)
* its protection is valid (or invalid/absent, but only if a callback function
* is present and yields a positive result using also the supplied argument)
* its transaction ID matches the previous transaction ID stored in ctx (if any)
* its recipNonce matches the previous senderNonce stored in the ctx (if any)
*
@@ -660,35 +699,29 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
if (msg->header->protectionAlg != 0) {
/* detect explicitly permitted exceptions for invalid protection */
if (!OSSL_CMP_validate_msg(ctx, msg)
&& (cb == NULL || !(*cb)(ctx, msg, 1, cb_arg))) {
&& (cb == NULL || (*cb)(ctx, msg, 1, cb_arg) <= 0)) {
CMPerr(0, CMP_R_ERROR_VALIDATING_PROTECTION);
return -1;
}
} else {
/* detect explicitly permitted exceptions for missing protection */
if (cb == NULL || !(*cb)(ctx, msg, 0, cb_arg)) {
if (cb == NULL || (*cb)(ctx, msg, 0, cb_arg) <= 0) {
CMPerr(0, CMP_R_MISSING_PROTECTION);
return -1;
}
}
/*
* Store any provided extraCerts in ctx for future use,
* such that they are available to ctx->certConf_cb and
* the peer does not need to send them again in the same transaction.
* For efficiency, the extraCerts are prepended so they get used first.
*/
if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts,
0 /* this allows self-issued certs */,
1 /* no_dups */, 1 /* prepend */))
return -1;
/* check CMP version number in header */
if (ossl_cmp_hdr_get_pvno(OSSL_CMP_MSG_get0_header(msg)) != OSSL_CMP_PVNO) {
CMPerr(0, CMP_R_UNEXPECTED_PVNO);
return -1;
}
if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
CMPerr(0, CMP_R_PKIBODY_ERROR);
return -1;
}
/* compare received transactionID with the expected one in previous msg */
if (ctx->transactionID != NULL
&& (msg->header->transactionID == NULL
@@ -720,10 +753,17 @@ int ossl_cmp_msg_check_received(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg,
&& !OSSL_CMP_CTX_set1_transactionID(ctx, msg->header->transactionID))
return -1;
if ((rcvd_type = ossl_cmp_msg_get_bodytype(msg)) < 0) {
CMPerr(0, CMP_R_PKIBODY_ERROR);
/*
* Store any provided extraCerts in ctx for future use,
* such that they are available to ctx->certConf_cb and
* the peer does not need to send them again in the same transaction.
* For efficiency, the extraCerts are prepended so they get used first.
*/
if (!ossl_cmp_sk_X509_add1_certs(ctx->untrusted_certs, msg->extraCerts,
0 /* this allows self-issued certs */,
1 /* no_dups */, 1 /* prepend */))
return -1;
}
return rcvd_type;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
+47
View File
@@ -248,6 +248,27 @@ int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms,
size_t enckeylen;
size_t ceklen;
CMS_EncryptedContentInfo *ec;
{
/*
* TODO(3.0) Remove this when we have functionality to deserialize
* parameters in EVP_PKEY form from an X509_ALGOR.
* This is needed to be able to replace the EC_KEY specific decoding
* that happens in ecdh_cms_set_peerkey() (crypto/ec/ec_ameth.c)
*
* THIS IS TEMPORARY
*/
EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
EVP_PKEY_get0(pkey);
if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT,
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
goto err;
}
}
enckeylen = rek->encryptedKey->length;
enckey = rek->encryptedKey->data;
/* Setup all parameters to derive KEK */
@@ -446,6 +467,32 @@ int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
STACK_OF(CMS_RecipientEncryptedKey) *reks;
int i;
{
/*
* TODO(3.0) Remove this when we have figured out all the details
* need to set up encryption right. With legacy keys, a *lot* is
* happening in the CMS specific EVP_PKEY_ASN1_METHOD functions,
* such as automatically setting a default KDF type, KDF digest,
* all that kind of stuff.
* With EVP_SIGNATURE, setting a default digest is done by getting
* the default MD for the key, and then inject that back into the
* signature implementation... we could do something similar with
* CMS, possibly using CMS specific OSSL_PARAM keys, just like we
* have for certain AlgorithmIdentifier retrievals.
*
* THIS IS TEMPORARY
*/
EVP_PKEY_CTX *pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
EVP_PKEY_get0(pkey);
if (EVP_PKEY_id(pkey) == EVP_PKEY_NONE) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT,
CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
return 0;
}
}
if (ri->type != CMS_RECIPINFO_AGREE) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT, CMS_R_NOT_KEY_AGREEMENT);
return 0;
+8 -2
View File
@@ -174,7 +174,7 @@ int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
* the "CONF classic" functions, for consistency.
*/
CONF *NCONF_new(CONF_METHOD *meth)
CONF *NCONF_new_with_libctx(OPENSSL_CTX *libctx, CONF_METHOD *meth)
{
CONF *ret;
@@ -183,13 +183,19 @@ CONF *NCONF_new(CONF_METHOD *meth)
ret = meth->create(meth);
if (ret == NULL) {
CONFerr(CONF_F_NCONF_NEW, ERR_R_MALLOC_FAILURE);
CONFerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->libctx = libctx;
return ret;
}
CONF *NCONF_new(CONF_METHOD *meth)
{
return NCONF_new_with_libctx(NULL, meth);
}
void NCONF_free(CONF *conf)
{
if (conf == NULL)
+33 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -13,8 +13,10 @@
#include <openssl/crypto.h>
#include "internal/conf.h"
#include "internal/dso.h"
#include "internal/thread_once.h"
#include <openssl/x509.h>
#include <openssl/trace.h>
#include <openssl/engine.h>
#define DSO_mod_init_name "OPENSSL_init"
#define DSO_mod_finish_name "OPENSSL_finish"
@@ -55,6 +57,8 @@ struct conf_imodule_st {
static STACK_OF(CONF_MODULE) *supported_modules = NULL;
static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT;
static void module_free(CONF_MODULE *md);
static void module_finish(CONF_IMODULE *imod);
static int module_run(const CONF *cnf, const char *name, const char *value,
@@ -113,22 +117,25 @@ int CONF_modules_load(const CONF *cnf, const char *appname,
}
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags)
int CONF_modules_load_file_with_libctx(OPENSSL_CTX *libctx,
const char *filename,
const char *appname, unsigned long flags)
{
char *file = NULL;
CONF *conf = NULL;
int ret = 0;
conf = NCONF_new(NULL);
conf = NCONF_new_with_libctx(libctx, NULL);
if (conf == NULL)
goto err;
if (filename == NULL) {
file = CONF_get1_default_config_file();
if (!file)
if (file == NULL)
goto err;
} else
} else {
file = (char *)filename;
}
if (NCONF_load(conf, file, NULL) <= 0) {
if ((flags & CONF_MFLAGS_IGNORE_MISSING_FILE) &&
@@ -152,12 +159,32 @@ int CONF_modules_load_file(const char *filename, const char *appname,
return ret;
}
int CONF_modules_load_file(const char *filename,
const char *appname, unsigned long flags)
{
return CONF_modules_load_file_with_libctx(NULL, filename, appname, flags);
}
DEFINE_RUN_ONCE_STATIC(do_load_builtin_modules)
{
OPENSSL_load_builtin_modules();
#ifndef OPENSSL_NO_ENGINE
/* Need to load ENGINEs */
ENGINE_load_builtin_engines();
#endif
ERR_clear_error();
return 1;
}
static int module_run(const CONF *cnf, const char *name, const char *value,
unsigned long flags)
{
CONF_MODULE *md;
int ret;
if (!RUN_ONCE(&load_builtin_modules, do_load_builtin_modules))
return -1;
md = module_find(name);
/* Module not found: try to load DSO */
-6
View File
@@ -59,12 +59,6 @@ int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings)
filename, appname, flags);
#endif
OPENSSL_load_builtin_modules();
#ifndef OPENSSL_NO_ENGINE
/* Need to load ENGINEs */
ENGINE_load_builtin_engines();
#endif
ERR_clear_error();
#ifndef OPENSSL_SYS_UEFI
ret = CONF_modules_load_file(filename, appname, flags);
#endif
+17
View File
@@ -8,6 +8,7 @@
*/
#include "crypto/cryptlib.h"
#include <openssl/conf.h>
#include "internal/thread_once.h"
#include "internal/property.h"
@@ -145,6 +146,13 @@ OPENSSL_CTX *OPENSSL_CTX_new(void)
return ctx;
}
#ifndef FIPS_MODE
int OPENSSL_CTX_load_config(OPENSSL_CTX *ctx, const char *config_file)
{
return CONF_modules_load_file_with_libctx(ctx, config_file, NULL, 0) > 0;
}
#endif
void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
{
if (ctx != NULL)
@@ -164,6 +172,15 @@ OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)
return ctx;
}
int openssl_ctx_is_default(OPENSSL_CTX *ctx)
{
#ifndef FIPS_MODE
if (ctx == NULL || ctx == default_context)
return 1;
#endif
return 0;
}
static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
CRYPTO_EX_DATA *ad, int index,
long argl_ign, void *argp)
+10 -3
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -30,6 +30,15 @@ static const ERR_STRING_DATA CRMF_str_reasons[] = {
"iterationcount below 100"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_MALFORMED_IV), "malformed iv"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_NULL_ARGUMENT), "null argument"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY),
"popo inconsistent public key"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING), "popo missing"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_PUBLIC_KEY),
"popo missing public key"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_MISSING_SUBJECT),
"popo missing subject"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED),
"popo raverified not accepted"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_MAC_ALGOR_FAILURE),
"setting mac algor failure"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_SETTING_OWF_ALGOR_FAILURE),
@@ -44,8 +53,6 @@ static const ERR_STRING_DATA CRMF_str_reasons[] = {
"unsupported method for creating popo"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_METHOD),
"unsupported popo method"},
{ERR_PACK(ERR_LIB_CRMF, 0, CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED),
"unsupported popo not accepted"},
{0, NULL}
};
+63 -82
View File
@@ -303,7 +303,7 @@ static int crmf_asn1_get_int(const ASN1_INTEGER *a)
return (int)res;
}
int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm)
int OSSL_CRMF_MSG_get_certReqId(const OSSL_CRMF_MSG *crm)
{
if (crm == NULL || /* not really needed: */ crm->certReq == NULL) {
CRMFerr(CRMF_F_OSSL_CRMF_MSG_GET_CERTREQID, CRMF_R_NULL_ARGUMENT);
@@ -367,65 +367,30 @@ static int CRMF_poposigningkey_init(OSSL_CRMF_POPOSIGNINGKEY *ps,
OSSL_CRMF_CERTREQUEST *cr,
EVP_PKEY *pkey, int dgst)
{
int len;
size_t crlen;
size_t siglen;
unsigned char *crder = NULL, *sig = NULL;
int alg_nid = 0;
int md_nid = 0;
const EVP_MD *alg = NULL;
EVP_MD_CTX *ctx = NULL;
int ret = 0;
EVP_MD *fetched_md = NULL;
const EVP_MD *md = EVP_get_digestbynid(dgst);
if (ps == NULL || cr == NULL || pkey == NULL) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_NULL_ARGUMENT);
return 0;
}
/* OpenSSL defaults all bit strings to be encoded as ASN.1 NamedBitList */
ps->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
ps->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
/* If we didn't find legacy MD, we try an implicit fetch */
if (md == NULL)
md = fetched_md = EVP_MD_fetch(NULL, OBJ_nid2sn(dgst), NULL);
len = i2d_OSSL_CRMF_CERTREQUEST(cr, &crder);
if (len < 0 || crder == NULL) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
goto err;
}
crlen = (size_t)len;
if (!OBJ_find_sigid_by_algs(&alg_nid, dgst, EVP_PKEY_id(pkey))) {
if (md == NULL) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT,
CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY);
goto err;
return 0;
}
if (!OBJ_find_sigid_algs(alg_nid, &md_nid, NULL)
|| (alg = EVP_get_digestbynid(md_nid)) == NULL) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT,
CRMF_R_UNSUPPORTED_ALG_FOR_POPSIGNINGKEY);
goto err;
}
if (!X509_ALGOR_set0(ps->algorithmIdentifier, OBJ_nid2obj(alg_nid),
V_ASN1_NULL, NULL)
|| (ctx = EVP_MD_CTX_new()) == NULL
|| EVP_DigestSignInit(ctx, NULL, alg, NULL, pkey) <= 0
|| EVP_DigestSignUpdate(ctx, crder, crlen) <= 0
|| EVP_DigestSignFinal(ctx, NULL, &siglen) <= 0) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
goto err;
}
if ((sig = OPENSSL_malloc(siglen)) == NULL)
goto err;
if (EVP_DigestSignFinal(ctx, sig, &siglen) <= 0
|| !ASN1_BIT_STRING_set(ps->signature, sig, siglen)) {
CRMFerr(CRMF_F_CRMF_POPOSIGNINGKEY_INIT, CRMF_R_ERROR);
goto err;
}
ret = 1;
err:
OPENSSL_free(crder);
EVP_MD_CTX_free(ctx);
OPENSSL_free(sig);
ret = ASN1_item_sign(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
ps->algorithmIdentifier, NULL, ps->signature,
cr, pkey, md);
EVP_MD_free(fetched_md);
return ret;
}
@@ -520,21 +485,29 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
X509_PUBKEY *pubkey = NULL;
OSSL_CRMF_POPOSIGNINGKEY *sig = NULL;
if (reqs == NULL
|| (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL
|| req->popo == NULL) {
CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO,
CRMF_R_NULL_ARGUMENT);
if (reqs == NULL || (req = sk_OSSL_CRMF_MSG_value(reqs, rid)) == NULL) {
CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO, CRMF_R_NULL_ARGUMENT);
return 0;
}
if (req->popo == NULL) {
CRMFerr(0, CRMF_R_POPO_MISSING);
return 0;
}
switch (req->popo->type) {
case OSSL_CRMF_POPO_RAVERIFIED:
if (acceptRAVerified)
return 1;
if (!acceptRAVerified) {
CRMFerr(0, CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED);
return 0;
}
break;
case OSSL_CRMF_POPO_SIGNATURE:
pubkey = req->certReq->certTemplate->publicKey;
if (pubkey == NULL) {
CRMFerr(0, CRMF_R_POPO_MISSING_PUBLIC_KEY);
return 0;
}
sig = req->popo->value.signature;
if (sig->poposkInput != NULL) {
/*
@@ -542,26 +515,34 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
* the public key from the certificate template. This MUST be
* exactly the same value as contained in the certificate template.
*/
const ASN1_ITEM *rptr = ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT);
if (pubkey == NULL
|| sig->poposkInput->publicKey == NULL
|| X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey)
|| ASN1_item_verify(rptr, sig->algorithmIdentifier,
sig->signature, sig->poposkInput,
X509_PUBKEY_get0(pubkey)) < 1)
break;
if (sig->poposkInput->publicKey == NULL) {
CRMFerr(0, CRMF_R_POPO_MISSING_PUBLIC_KEY);
return 0;
}
if (X509_PUBKEY_cmp(pubkey, sig->poposkInput->publicKey) != 0) {
CRMFerr(0, CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY);
return 0;
}
/*
* TODO check the contents of the authInfo sub-field,
* see RFC 4211 https://tools.ietf.org/html/rfc4211#section-4.1
*/
if (ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_POPOSIGNINGKEYINPUT),
sig->algorithmIdentifier, sig->signature,
sig->poposkInput,
X509_PUBKEY_get0(pubkey)) < 1)
return 0;
} else {
if (pubkey == NULL
|| req->certReq->certTemplate->subject == NULL
|| ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
sig->algorithmIdentifier,
sig->signature,
req->certReq,
X509_PUBKEY_get0(pubkey)) < 1)
break;
if (req->certReq->certTemplate->subject == NULL) {
CRMFerr(0, CRMF_R_POPO_MISSING_SUBJECT);
return 0;
}
if (ASN1_item_verify(ASN1_ITEM_rptr(OSSL_CRMF_CERTREQUEST),
sig->algorithmIdentifier, sig->signature,
req->certReq, X509_PUBKEY_get0(pubkey)) < 1)
return 0;
}
return 1;
break;
case OSSL_CRMF_POPO_KEYENC:
/*
* TODO: when OSSL_CMP_certrep_new() supports encrypted certs,
@@ -575,25 +556,25 @@ int OSSL_CRMF_MSGS_verify_popo(const OSSL_CRMF_MSGS *reqs,
CRMF_R_UNSUPPORTED_POPO_METHOD);
return 0;
}
CRMFerr(CRMF_F_OSSL_CRMF_MSGS_VERIFY_POPO,
CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED);
return 0;
return 1;
}
/* retrieves the serialNumber of the given cert template or NULL on error */
ASN1_INTEGER *OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(OSSL_CRMF_CERTTEMPLATE *tmpl)
ASN1_INTEGER
*OSSL_CRMF_CERTTEMPLATE_get0_serialNumber(const OSSL_CRMF_CERTTEMPLATE *tmpl)
{
return tmpl != NULL ? tmpl->serialNumber : NULL;
}
/* retrieves the issuer name of the given cert template or NULL on error */
X509_NAME *OSSL_CRMF_CERTTEMPLATE_get0_issuer(OSSL_CRMF_CERTTEMPLATE *tmpl)
const X509_NAME
*OSSL_CRMF_CERTTEMPLATE_get0_issuer(const OSSL_CRMF_CERTTEMPLATE *tmpl)
{
return tmpl != NULL ? tmpl->issuer : NULL;
}
/* retrieves the issuer name of the given CertId or NULL on error */
X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
const X509_NAME *OSSL_CRMF_CERTID_get0_issuer(const OSSL_CRMF_CERTID *cid)
{
return cid != NULL && cid->issuer->type == GEN_DIRNAME ?
cid->issuer->d.directoryName : NULL;
@@ -619,9 +600,9 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
CRMFerr(CRMF_F_OSSL_CRMF_CERTTEMPLATE_FILL, CRMF_R_NULL_ARGUMENT);
return 0;
}
if (subject != NULL && !X509_NAME_set(&tmpl->subject, subject))
if (subject != NULL && !X509_NAME_set((X509_NAME **)&tmpl->subject, subject))
return 0;
if (issuer != NULL && !X509_NAME_set(&tmpl->issuer, issuer))
if (issuer != NULL && !X509_NAME_set((X509_NAME **)&tmpl->issuer, issuer))
return 0;
if (serial != NULL) {
ASN1_INTEGER_free(tmpl->serialNumber);
@@ -641,7 +622,7 @@ int OSSL_CRMF_CERTTEMPLATE_fill(OSSL_CRMF_CERTTEMPLATE *tmpl,
* returns a pointer to the decrypted certificate
* returns NULL on error or if no certificate available
*/
X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert,
X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(const OSSL_CRMF_ENCRYPTEDVALUE *ecert,
EVP_PKEY *pkey)
{
X509 *cert = NULL; /* decrypted certificate */
+2 -2
View File
@@ -315,9 +315,9 @@ struct ossl_crmf_certtemplate_st {
/* This field is assigned by the CA during certificate creation */
X509_ALGOR *signingAlg; /* signingAlg MUST be omitted */
/* This field is assigned by the CA during certificate creation */
X509_NAME *issuer;
const X509_NAME *issuer;
OSSL_CRMF_OPTIONALVALIDITY *validity;
X509_NAME *subject;
const X509_NAME *subject;
X509_PUBKEY *publicKey;
ASN1_BIT_STRING *issuerUID; /* deprecated in version 2 */
/* According to rfc 3280: UniqueIdentifier ::= BIT STRING */
+14 -5
View File
@@ -132,7 +132,9 @@ SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
* 0 on decoding failure, or invalid parameter if any
* -1 on internal (malloc) failure
*/
int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *name)
int CTLOG_new_from_base64_with_libctx(CTLOG **ct_log, const char *pkey_base64,
const char *name, OPENSSL_CTX *libctx,
const char *propq)
{
unsigned char *pkey_der = NULL;
int pkey_der_len;
@@ -140,13 +142,13 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n
EVP_PKEY *pkey = NULL;
if (ct_log == NULL) {
CTerr(CT_F_CTLOG_NEW_FROM_BASE64, ERR_R_PASSED_INVALID_ARGUMENT);
CTerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der);
if (pkey_der_len < 0) {
CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY);
CTerr(0, CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
@@ -154,11 +156,11 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n
pkey = d2i_PUBKEY(NULL, &p, pkey_der_len);
OPENSSL_free(pkey_der);
if (pkey == NULL) {
CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY);
CTerr(0, CT_R_LOG_CONF_INVALID_KEY);
return 0;
}
*ct_log = CTLOG_new(pkey, name);
*ct_log = CTLOG_new_with_libctx(pkey, name, libctx, propq);
if (*ct_log == NULL) {
EVP_PKEY_free(pkey);
return 0;
@@ -166,3 +168,10 @@ int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, const char *n
return 1;
}
int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64,
const char *name)
{
return CTLOG_new_from_base64_with_libctx(ct_log, pkey_base64, name, NULL,
NULL);
}
+7 -1
View File
@@ -100,6 +100,9 @@ struct sct_ctx_st {
size_t prederlen;
/* milliseconds since epoch (to check that the SCT isn't from the future) */
uint64_t epoch_time_in_ms;
OPENSSL_CTX *libctx;
char *propq;
};
/* Context when evaluating whether a Certificate Transparency policy is met */
@@ -109,12 +112,15 @@ struct ct_policy_eval_ctx_st {
CTLOG_STORE *log_store;
/* milliseconds since epoch (to check that SCTs aren't from the future) */
uint64_t epoch_time_in_ms;
OPENSSL_CTX *libctx;
char *propq;
};
/*
* Creates a new context for verifying an SCT.
*/
SCT_CTX *SCT_CTX_new(void);
SCT_CTX *SCT_CTX_new(OPENSSL_CTX *ctx, const char *propq);
/*
* Deletes an SCT verification context.
*/
+60 -14
View File
@@ -22,6 +22,8 @@
* Information about a CT log server.
*/
struct ctlog_st {
OPENSSL_CTX *libctx;
char *propq;
char *name;
uint8_t log_id[CT_V1_HASHLEN];
EVP_PKEY *public_key;
@@ -32,6 +34,8 @@ struct ctlog_st {
* It takes ownership of any CTLOG instances added to it.
*/
struct ctlog_store_st {
OPENSSL_CTX *libctx;
char *propq;
STACK_OF(CTLOG) *logs;
};
@@ -70,53 +74,78 @@ static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX* ctx)
}
/* Converts a log's public key into a SHA256 log ID */
static int ct_v1_log_id_from_pkey(EVP_PKEY *pkey,
unsigned char log_id[CT_V1_HASHLEN])
static int ct_v1_log_id_from_pkey(CTLOG *log, EVP_PKEY *pkey)
{
int ret = 0;
unsigned char *pkey_der = NULL;
int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
unsigned int len;
EVP_MD *sha256 = NULL;
if (pkey_der_len <= 0) {
CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, CT_R_LOG_KEY_INVALID);
goto err;
}
sha256 = EVP_MD_fetch(log->libctx, "SHA2-256", log->propq);
if (sha256 == NULL) {
CTerr(CT_F_CT_V1_LOG_ID_FROM_PKEY, ERR_LIB_EVP);
goto err;
}
ret = EVP_Digest(pkey_der, pkey_der_len, log_id, &len, EVP_sha256(), NULL);
ret = EVP_Digest(pkey_der, pkey_der_len, log->log_id, &len, sha256,
NULL);
err:
EVP_MD_free(sha256);
OPENSSL_free(pkey_der);
return ret;
}
CTLOG_STORE *CTLOG_STORE_new(void)
CTLOG_STORE *CTLOG_STORE_new_with_libctx(OPENSSL_CTX *libctx, const char *propq)
{
CTLOG_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
CTerr(CT_F_CTLOG_STORE_NEW, ERR_R_MALLOC_FAILURE);
CTerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->libctx = libctx;
if (propq != NULL) {
ret->propq = OPENSSL_strdup(propq);
if (ret->propq == NULL) {
CTerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ret->logs = sk_CTLOG_new_null();
if (ret->logs == NULL)
if (ret->logs == NULL) {
CTerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
return ret;
err:
OPENSSL_free(ret);
CTLOG_STORE_free(ret);
return NULL;
}
CTLOG_STORE *CTLOG_STORE_new(void)
{
return CTLOG_STORE_new_with_libctx(NULL, NULL);
}
void CTLOG_STORE_free(CTLOG_STORE *store)
{
if (store != NULL) {
OPENSSL_free(store->propq);
sk_CTLOG_pop_free(store->logs, CTLOG_free);
OPENSSL_free(store);
}
}
static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section)
static int ctlog_new_from_conf(CTLOG_STORE *store, CTLOG **ct_log,
const CONF *conf, const char *section)
{
const char *description = NCONF_get_string(conf, section, "description");
char *pkey_base64;
@@ -132,7 +161,8 @@ static int ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *sec
return 0;
}
return CTLOG_new_from_base64(ct_log, pkey_base64, description);
return CTLOG_new_from_base64_with_libctx(ct_log, pkey_base64, description,
store->libctx, store->propq);
}
int CTLOG_STORE_load_default_file(CTLOG_STORE *store)
@@ -168,7 +198,7 @@ static int ctlog_store_load_log(const char *log_name, int log_name_len,
if (tmp == NULL)
goto mem_err;
ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp);
ret = ctlog_new_from_conf(load_ctx->log_store, &ct_log, load_ctx->conf, tmp);
OPENSSL_free(tmp);
if (ret < 0) {
@@ -234,22 +264,32 @@ end:
* Takes ownership of the public key.
* Copies the name.
*/
CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
CTLOG *CTLOG_new_with_libctx(EVP_PKEY *public_key, const char *name,
OPENSSL_CTX *libctx, const char *propq)
{
CTLOG *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
CTerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->libctx = libctx;
if (propq != NULL) {
ret->name = OPENSSL_strdup(propq);
if (ret->propq == NULL) {
CTerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
}
ret->name = OPENSSL_strdup(name);
if (ret->name == NULL) {
CTerr(CT_F_CTLOG_NEW, ERR_R_MALLOC_FAILURE);
CTerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1)
if (ct_v1_log_id_from_pkey(ret, public_key) != 1)
goto err;
ret->public_key = public_key;
@@ -259,12 +299,18 @@ err:
return NULL;
}
CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name)
{
return CTLOG_new_with_libctx(public_key, name, NULL, NULL);
}
/* Frees CT log and associated structures */
void CTLOG_free(CTLOG *log)
{
if (log != NULL) {
OPENSSL_free(log->name);
EVP_PKEY_free(log->public_key);
OPENSSL_free(log->propq);
OPENSSL_free(log);
}
}
+18 -2
View File
@@ -25,15 +25,25 @@
*/
static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300;
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new_with_libctx(OPENSSL_CTX *libctx,
const char *propq)
{
CT_POLICY_EVAL_CTX *ctx = OPENSSL_zalloc(sizeof(CT_POLICY_EVAL_CTX));
if (ctx == NULL) {
CTerr(CT_F_CT_POLICY_EVAL_CTX_NEW, ERR_R_MALLOC_FAILURE);
CTerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ctx->libctx = libctx;
if (propq != NULL) {
ctx->propq = OPENSSL_strdup(propq);
if (ctx->propq == NULL) {
CTerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
}
/* time(NULL) shouldn't ever fail, so don't bother checking for -1. */
ctx->epoch_time_in_ms = (uint64_t)(time(NULL) + SCT_CLOCK_DRIFT_TOLERANCE) *
1000;
@@ -41,12 +51,18 @@ CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
return ctx;
}
CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void)
{
return CT_POLICY_EVAL_CTX_new_with_libctx(NULL, NULL);
}
void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx)
{
if (ctx == NULL)
return;
X509_free(ctx->cert);
X509_free(ctx->issuer);
OPENSSL_free(ctx->propq);
OPENSSL_free(ctx);
}
+1 -1
View File
@@ -312,7 +312,7 @@ int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
return 0;
}
sctx = SCT_CTX_new();
sctx = SCT_CTX_new(ctx->libctx, ctx->propq);
if (sctx == NULL)
goto err;
+22 -6
View File
@@ -20,13 +20,23 @@
#include "ct_local.h"
SCT_CTX *SCT_CTX_new(void)
SCT_CTX *SCT_CTX_new(OPENSSL_CTX *libctx, const char *propq)
{
SCT_CTX *sctx = OPENSSL_zalloc(sizeof(*sctx));
if (sctx == NULL)
CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE);
sctx->libctx = libctx;
if (propq != NULL) {
sctx->propq = OPENSSL_strdup(propq);
if (sctx->propq == NULL) {
CTerr(CT_F_SCT_CTX_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(sctx);
return NULL;
}
}
return sctx;
}
@@ -39,6 +49,7 @@ void SCT_CTX_free(SCT_CTX *sctx)
OPENSSL_free(sctx->ihash);
OPENSSL_free(sctx->certder);
OPENSSL_free(sctx->preder);
OPENSSL_free(sctx->propq);
OPENSSL_free(sctx);
}
@@ -191,13 +202,17 @@ err:
return 0;
}
__owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
size_t *hash_len)
__owur static int ct_public_key_hash(SCT_CTX *sctx, X509_PUBKEY *pkey,
unsigned char **hash, size_t *hash_len)
{
int ret = 0;
unsigned char *md = NULL, *der = NULL;
int der_len;
unsigned int md_len;
EVP_MD *sha256 = EVP_MD_fetch(sctx->libctx, "SHA2-256", sctx->propq);
if (sha256 == NULL)
goto err;
/* Reuse buffer if possible */
if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
@@ -213,7 +228,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
if (der_len <= 0)
goto err;
if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
if (!EVP_Digest(der, der_len, md, &md_len, sha256, NULL))
goto err;
if (md != *hash) {
@@ -225,6 +240,7 @@ __owur static int ct_public_key_hash(X509_PUBKEY *pkey, unsigned char **hash,
md = NULL;
ret = 1;
err:
EVP_MD_free(sha256);
OPENSSL_free(md);
OPENSSL_free(der);
return ret;
@@ -237,7 +253,7 @@ int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
{
return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
return ct_public_key_hash(sctx, pubkey, &sctx->ihash, &sctx->ihashlen);
}
int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
@@ -247,7 +263,7 @@ int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
if (pkey == NULL)
return 0;
if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
if (!ct_public_key_hash(sctx, pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
EVP_PKEY_free(pkey);
return 0;
}
+2 -1
View File
@@ -122,7 +122,8 @@ int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
if (ctx == NULL)
goto end;
if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey))
if (!EVP_DigestVerifyInit_ex(ctx, NULL, "SHA2-256", sctx->propq, sctx->pkey,
sctx->libctx))
goto end;
if (!sct_ctx_update(ctx, sctx, sct))
+142
View File
@@ -0,0 +1,142 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <string.h>
#include "internal/cryptlib.h"
#include "internal/der.h"
#include "crypto/bn.h"
static int int_start_context(WPACKET *pkt, int tag)
{
if (tag < 0)
return 1;
if (!ossl_assert(tag <= 30))
return 0;
return WPACKET_start_sub_packet(pkt);
}
static int int_end_context(WPACKET *pkt, int tag)
{
if (tag < 0)
return 1;
if (!ossl_assert(tag <= 30))
return 0;
return WPACKET_close(pkt)
&& WPACKET_put_bytes_u8(pkt, DER_C_CONTEXT | tag);
}
int DER_w_precompiled(WPACKET *pkt, int tag,
const unsigned char *precompiled, size_t precompiled_n)
{
return int_start_context(pkt, tag)
&& WPACKET_memcpy(pkt, precompiled, precompiled_n)
&& int_end_context(pkt, tag);
}
int DER_w_boolean(WPACKET *pkt, int tag, int b)
{
return int_start_context(pkt, tag)
&& WPACKET_start_sub_packet(pkt)
&& (!b || WPACKET_put_bytes_u8(pkt, 0xFF))
&& !WPACKET_close(pkt)
&& !WPACKET_put_bytes_u8(pkt, DER_P_BOOLEAN)
&& int_end_context(pkt, tag);
}
static int int_der_w_integer(WPACKET *pkt, int tag,
int (*put_bytes)(WPACKET *pkt, const void *v,
unsigned int *top_byte),
const void *v)
{
unsigned int top_byte = 0;
return int_start_context(pkt, tag)
&& WPACKET_start_sub_packet(pkt)
&& put_bytes(pkt, v, &top_byte)
&& ((top_byte & 0x80) == 0 || WPACKET_put_bytes_u8(pkt, 0))
&& WPACKET_close(pkt)
&& WPACKET_put_bytes_u8(pkt, DER_P_INTEGER)
&& int_end_context(pkt, tag);
}
static int int_put_bytes_ulong(WPACKET *pkt, const void *v,
unsigned int *top_byte)
{
const unsigned long *value = v;
unsigned long tmp = *value;
size_t n = 0;
while (tmp != 0) {
n++;
*top_byte = (tmp & 0xFF);
tmp >>= 8;
}
if (n == 0)
n = 1;
return WPACKET_put_bytes__(pkt, *value, n);
}
/* For integers, we only support unsigned values for now */
int DER_w_ulong(WPACKET *pkt, int tag, unsigned long v)
{
return int_der_w_integer(pkt, tag, int_put_bytes_ulong, &v);
}
static int int_put_bytes_bn(WPACKET *pkt, const void *v,
unsigned int *top_byte)
{
unsigned char *p = NULL;
size_t n = BN_num_bytes(v);
/* The BIGNUM limbs are in LE order */
*top_byte =
((bn_get_words(v) [(n - 1) / BN_BYTES]) >> (8 * ((n - 1) % BN_BYTES)))
& 0xFF;
if (!WPACKET_allocate_bytes(pkt, n, &p))
return 0;
if (p != NULL)
BN_bn2bin(v, p);
return 1;
}
int DER_w_bn(WPACKET *pkt, int tag, const BIGNUM *v)
{
if (v == NULL || BN_is_negative(v))
return 0;
if (BN_is_zero(v))
return DER_w_ulong(pkt, tag, 0);
return int_der_w_integer(pkt, tag, int_put_bytes_bn, v);
}
int DER_w_null(WPACKET *pkt, int tag)
{
return int_start_context(pkt, tag)
&& WPACKET_start_sub_packet(pkt)
&& WPACKET_close(pkt)
&& WPACKET_put_bytes_u8(pkt, DER_P_NULL)
&& int_end_context(pkt, tag);
}
/* Constructed things need a start and an end */
int DER_w_begin_sequence(WPACKET *pkt, int tag)
{
return int_start_context(pkt, tag)
&& WPACKET_start_sub_packet(pkt);
}
int DER_w_end_sequence(WPACKET *pkt, int tag)
{
return WPACKET_close(pkt)
&& WPACKET_put_bytes_u8(pkt, DER_F_CONSTRUCTED | DER_P_SEQUENCE)
&& int_end_context(pkt, tag);
}
+10 -7
View File
@@ -15,20 +15,23 @@ ENDIF
LIBS=../../libcrypto
$COMMON=set_key.c ecb3_enc.c $DESASM
SOURCE[../../libcrypto]=$COMMON\
ecb_enc.c cbc_enc.c \
cfb64enc.c cfb64ede.c cfb_enc.c \
ofb64ede.c ofb64enc.c ofb_enc.c \
str2key.c pcbc_enc.c qud_cksm.c rand_key.c \
fcrypt.c xcbc_enc.c cbc_cksm.c
$ALL=$COMMON\
ecb_enc.c cbc_enc.c \
cfb64enc.c cfb64ede.c cfb_enc.c \
ofb64ede.c ofb64enc.c ofb_enc.c \
str2key.c pcbc_enc.c qud_cksm.c rand_key.c \
fcrypt.c xcbc_enc.c cbc_cksm.c
SOURCE[../../libcrypto]=$ALL
SOURCE[../../providers/libfips.a]=$COMMON
DEFINE[../../libcrypto]=$DESDEF
DEFINE[../../providers/libfips.a]=$DESDEF
DEFINE[../../providers/liblegacy.a]=$DESDEF
# When all deprecated symbols are removed, libcrypto doesn't export the
# DES functions, so we must include them directly in liblegacy.a
IF[{- $disabled{'deprecated-3.0'} && !$disabled{"mdc2"} -}]
SOURCE[../../providers/liblegacy.a]=set_key.c $DESASM
SOURCE[../../providers/liblegacy.a]=$ALL
DEFINE[../../providers/liblegacy.a]=$DESDEF
ENDIF
+1 -1
View File
@@ -1,6 +1,6 @@
LIBS=../../libcrypto
$COMMON=dh_lib.c dh_key.c dh_group_params.c dh_check.c
$COMMON=dh_lib.c dh_key.c dh_group_params.c dh_check.c dh_backend.c
SOURCE[../../libcrypto]=$COMMON\
dh_asn1.c dh_gen.c dh_err.c dh_depr.c \
-5
View File
@@ -1,5 +0,0 @@
-----BEGIN DH PARAMETERS-----
MIGHAoGBAJf2QmHKtQXdKCjhPx1ottPb0PMTBH9A6FbaWMsTuKG/K3g6TG1Z1fkq
/Gz/PWk/eLI9TzFgqVAuPvr3q14a1aZeVUMTgo2oO5/y2UHe6VaJ+trqCTat3xlx
/mNbIK9HA2RgPC3gWfVLZQrY+gz3ASHHR5nXWHEyvpuZm7m3h+irAgEC
-----END DH PARAMETERS-----
-3
View File
@@ -1,3 +0,0 @@
-----BEGIN DH PARAMETERS-----
MB4CGQDUoLoCULb9LsYm5+/WN992xxbiLQlEuIsCAQM=
-----END DH PARAMETERS-----
-16
View File
@@ -1,16 +0,0 @@
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA7ZKJNYJFVcs7+6J2WmkEYb8h86tT0s0h2v94GRFS8Q7B4lW9aG9o
AFO5Imov5Jo0H2XMWTKKvbHbSe3fpxJmw/0hBHAY8H/W91hRGXKCeyKpNBgdL8sh
z22SrkO2qCnHJ6PLAMXy5fsKpFmFor2tRfCzrfnggTXu2YOzzK7q62bmqVdmufEo
pT8igNcLpvZxk5uBDvhakObMym9mX3rAEBoe8PwttggMYiiw7NuJKO4MqD1llGkW
aVM8U2ATsCun1IKHrRxynkE1/MJ86VHeYYX8GZt2YA8z+GuzylIOKcMH6JAWzMwA
Gbatw6QwizOhr9iMjZ0B26TE3X8LvW84wwIBAg==
-----END DH PARAMETERS-----
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEArtA3w73zP6Lu3EOQtwogiXt3AXXpuS6yD4BhzNS1pZFyPHk0/an5
8ydEkPhQZHKDW+BZJxxPLANaTudWo2YT8TgtvUdN6KSgMiEi6McwqDw+SADuvW+F
SKUYFxG6VFIxyEP6xBdf+vhJxEDbRG2EYsHDRRtJ76gp9cSKTHusf2R+4AAVGqnt
gRAbNqtcOar/7FSj+Pl8G3v0Bty0LcCSpbqgYlnv6z+rErQmmC6PPvSz97TDMCok
yKpCE9hFA1zkqK3TH4FmFvGeIaXJUIBZf4mArWuBTjWFW3nmhESRUn1VK3K3x42N
a5k6c2+EhrMFiLjxuH6JZoqL0/E93FF9SwIBAg==
-----END DH PARAMETERS-----
-14
View File
@@ -1,14 +0,0 @@
-----BEGIN DH PARAMETERS-----
MIICCAKCAgEA/urRnb6vkPYc/KEGXWnbCIOaKitq7ySIq9dTH7s+Ri59zs77zty7
vfVlSe6VFTBWgYjD2XKUFmtqq6CqXMhVX5ElUDoYDpAyTH85xqNFLzFC7nKrff/H
TFKNttp22cZE9V0IPpzedPfnQkE7aUdmF9JnDyv21Z/818O93u1B4r0szdnmEvEF
bKuIxEHX+bp0ZR7RqE1AeifXGJX3d6tsd2PMAObxwwsv55RGkn50vHO4QxtTARr1
rRUV5j3B3oPMgC7Offxx+98Xn45B1/G0Prp11anDsR1PGwtaCYipqsvMwQUSJtyE
EOQWk+yFkeMe4vWv367eEi0Sd/wnC+TSXBE3pYvpYerJ8n1MceI5GQTdarJ77OW9
bGTHmxRsLSCM1jpLdPja5jjb4siAa6EHc4qN9c/iFKS3PQPJEnX7pXKBRs5f7AF3
W3RIGt+G9IVNZfXaS7Z/iCpgzgvKCs0VeqN38QsJGtC1aIkwOeyjPNy2G6jJ4yqH
ovXYt/0mc00vCWeSNS1wren0pR2EiLxX0ypjjgsU1mk/Z3b/+zVf7fZSIB+nDLjb
NPtUlJCVGnAeBK1J1nG3TQicqowOXoM6ISkdaXj5GPJdXHab2+S7cqhKGv5qC7rR
jT6sx7RUr0CNTxzLI7muV2/a4tGmj0PSdXQdsZ7tw7gbXlaWT1+MM2MCAQI=
-----END DH PARAMETERS-----
-4
View File
@@ -1,4 +0,0 @@
-----BEGIN DH PARAMETERS-----
MEYCQQDaWDwW2YUiidDkr3VvTMqS3UvlM7gE+w/tlO+cikQD7VdGUNNpmdsp13Yn
a6LT1BLiGPTdHghM9tgAPnxHdOgzAgEC
-----END DH PARAMETERS-----
+58 -21
View File
@@ -20,10 +20,12 @@
#include "dh_local.h"
#include <openssl/bn.h>
#include "crypto/asn1.h"
#include "crypto/dh.h"
#include "crypto/evp.h"
#include <openssl/cms.h>
#include <openssl/core_names.h>
#include "internal/param_build.h"
#include "openssl/param_build.h"
#include "internal/ffc.h"
/*
* i2d/d2i like DH parameter functions which use the appropriate routine for
@@ -489,48 +491,82 @@ static size_t dh_pkey_dirty_cnt(const EVP_PKEY *pkey)
}
static int dh_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
const char *propq)
{
DH *dh = from->pkey.dh;
OSSL_PARAM_BLD tmpl;
OSSL_PARAM_BLD *tmpl;
const BIGNUM *p = DH_get0_p(dh), *g = DH_get0_g(dh), *q = DH_get0_q(dh);
const BIGNUM *pub_key = DH_get0_pub_key(dh);
const BIGNUM *priv_key = DH_get0_priv_key(dh);
OSSL_PARAM *params;
int rv;
OSSL_PARAM *params = NULL;
int selection = 0;
int rv = 0;
/*
* If the DH method is foreign, then we can't be sure of anything, and
* can therefore not export or pretend to export.
*/
if (dh_get_method(dh) != DH_OpenSSL())
return 0;
if (p == NULL || g == NULL)
return 0;
ossl_param_bld_init(&tmpl);
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
goto err;
if (q != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
return 0;
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q))
goto err;
}
selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
if (pub_key != NULL) {
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
}
/* A key must at least have a public part. */
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY, pub_key))
return 0;
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
priv_key))
return 0;
goto err;
selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
}
if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
return 0;
if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
/* We export, the provider imports */
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
ossl_param_bld_free(params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
OSSL_PARAM_BLD_free_params(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return rv;
}
static int dh_pkey_import_from(const OSSL_PARAM params[], void *key)
{
EVP_PKEY *pkey = key;
DH *dh = DH_new();
if (dh == NULL) {
ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ffc_fromdata(dh_get0_params(dh), params)
|| !dh_key_fromdata(dh, params)
|| !EVP_PKEY_assign_DH(pkey, dh)) {
DH_free(dh);
return 0;
}
return 1;
}
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
EVP_PKEY_DH,
EVP_PKEY_DH,
@@ -573,6 +609,7 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
dh_pkey_dirty_cnt,
dh_pkey_export_to,
dh_pkey_import_from,
};
const EVP_PKEY_ASN1_METHOD dhx_asn1_meth = {
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include "crypto/dh.h"
/*
* The intention with the "backend" source file is to offer backend functions
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int dh_key_fromdata(DH *dh, const OSSL_PARAM params[])
{
const OSSL_PARAM *param_priv_key, *param_pub_key;
BIGNUM *priv_key = NULL, *pub_key = NULL;
if (dh == NULL)
return 0;
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
param_pub_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
/*
* DH documentation says that a public key must be present if a
* private key is present.
* We want to have at least a public key either way, so we end up
* requiring it unconditionally.
*/
if (param_priv_key != NULL && param_pub_key == NULL)
return 0;
if ((param_priv_key != NULL
&& !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|| (param_pub_key != NULL
&& !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
goto err;
if (!DH_set0_key(dh, pub_key, priv_key))
goto err;
return 1;
err:
BN_clear_free(priv_key);
BN_free(pub_key);
return 0;
}
+6 -1
View File
@@ -45,6 +45,11 @@ int DH_set_method(DH *dh, const DH_METHOD *meth)
return 1;
}
const DH_METHOD *dh_get_method(const DH *dh)
{
return dh->meth;
}
DH *DH_new(void)
{
return dh_new_intern(NULL, NULL);
@@ -166,7 +171,7 @@ int DH_set_ex_data(DH *d, int idx, void *arg)
return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
}
void *DH_get_ex_data(DH *d, int idx)
void *DH_get_ex_data(const DH *d, int idx)
{
return CRYPTO_get_ex_data(&d->ex_data, idx);
}
+2 -2
View File
@@ -1,7 +1,7 @@
LIBS=../../libcrypto
$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_aid.c dsa_check.c \
dsa_key.c
$COMMON=dsa_sign.c dsa_vrf.c dsa_lib.c dsa_ossl.c dsa_check.c \
dsa_key.c dsa_backend.c
SOURCE[../../libcrypto]=$COMMON\
dsa_gen.c dsa_asn1.c \
-70
View File
@@ -1,70 +0,0 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include <openssl/objects.h>
#include "crypto/dsa.h"
#define ASN1_SEQUENCE 0x30
#define ASN1_OID 0x06
/*
* id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
* iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3
* }
*/
#define ENCODE_ALGORITHMIDENTIFIER_RFC3279(name, n) \
static const unsigned char algorithmidentifier_##name##_der[] = { \
ASN1_SEQUENCE, 0x09, \
ASN1_OID, 0x07, 1 * 40 + 2, 134, 72, 206, 56, 4, n \
}
ENCODE_ALGORITHMIDENTIFIER_RFC3279(sha1, 3);
/*
* dsaWithSHAx OIDs are of the form: (sigAlgs |n|)
* where sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
*/
#define ENCODE_ALGORITHMIDENTIFIER_SIGALGS(name, n) \
static const unsigned char algorithmidentifier_##name##_der[] = { \
ASN1_SEQUENCE, 0x0b, \
ASN1_OID, 0x09, 2 * 40 + 16, 0x86, 0x48, 1, 101, 3, 4, 3, n \
}
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha224, 1);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha256, 2);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha384, 3);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha512, 4);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_224, 5);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_256, 6);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_384, 7);
ENCODE_ALGORITHMIDENTIFIER_SIGALGS(sha3_512, 8);
#define MD_CASE(name) \
case NID_##name: \
*len = sizeof(algorithmidentifier_##name##_der); \
return algorithmidentifier_##name##_der
const unsigned char *dsa_algorithmidentifier_encoding(int md_nid, size_t *len)
{
switch (md_nid) {
MD_CASE(sha1);
MD_CASE(sha224);
MD_CASE(sha256);
MD_CASE(sha384);
MD_CASE(sha512);
MD_CASE(sha3_224);
MD_CASE(sha3_256);
MD_CASE(sha3_384);
MD_CASE(sha3_512);
default:
return NULL;
}
}
+59 -20
View File
@@ -21,8 +21,10 @@
#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#include "crypto/asn1.h"
#include "crypto/dsa.h"
#include "crypto/evp.h"
#include "internal/param_build.h"
#include "openssl/param_build.h"
#include "internal/ffc.h"
#include "dsa_local.h"
static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
@@ -518,45 +520,81 @@ static size_t dsa_pkey_dirty_cnt(const EVP_PKEY *pkey)
}
static int dsa_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
const char *propq)
{
DSA *dsa = from->pkey.dsa;
OSSL_PARAM_BLD tmpl;
OSSL_PARAM_BLD *tmpl;
const BIGNUM *p = DSA_get0_p(dsa), *g = DSA_get0_g(dsa);
const BIGNUM *q = DSA_get0_q(dsa), *pub_key = DSA_get0_pub_key(dsa);
const BIGNUM *priv_key = DSA_get0_priv_key(dsa);
OSSL_PARAM *params;
int rv;
int selection = 0;
int rv = 0;
/*
* If the DSA method is foreign, then we can't be sure of anything, and
* can therefore not export or pretend to export.
*/
if (DSA_get_method(dsa) != DSA_OpenSSL())
return 0;
if (p == NULL || q == NULL || g == NULL)
return 0;
ossl_param_bld_init(&tmpl);
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
|| !ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_FFC_G, g))
return 0;
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
pub_key))
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, p)
|| !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, q)
|| !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, g))
goto err;
selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
if (pub_key != NULL) {
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
pub_key))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
}
if (priv_key != NULL) {
if (!ossl_param_bld_push_BN(&tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY,
priv_key))
return 0;
goto err;
selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
}
if ((params = ossl_param_bld_to_param(&tmpl)) == NULL)
return 0;
if ((params = OSSL_PARAM_BLD_to_param(tmpl)) == NULL)
goto err;
/* We export, the provider imports */
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
ossl_param_bld_free(params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
OSSL_PARAM_BLD_free_params(params);
err:
OSSL_PARAM_BLD_free(tmpl);
return rv;
}
static int dsa_pkey_import_from(const OSSL_PARAM params[], void *key)
{
EVP_PKEY *pkey = key;
DSA *dsa = DSA_new();
if (dsa == NULL) {
ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ffc_fromdata(dsa_get0_params(dsa), params)
|| !dsa_key_fromdata(dsa, params)
|| !EVP_PKEY_assign_DSA(pkey, dsa)) {
DSA_free(dsa);
return 0;
}
return 1;
}
/* NB these are sorted in pkey_id order, lowest first */
const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = {
@@ -620,6 +658,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[5] = {
NULL, NULL, NULL, NULL,
dsa_pkey_dirty_cnt,
dsa_pkey_export_to
dsa_pkey_export_to,
dsa_pkey_import_from
}
};
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include "crypto/dsa.h"
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[])
{
const OSSL_PARAM *param_priv_key, *param_pub_key;
BIGNUM *priv_key = NULL, *pub_key = NULL;
if (dsa == NULL)
return 0;
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
param_pub_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
/* It's ok if neither half is present */
if (param_priv_key == NULL && param_pub_key == NULL)
return 1;
/*
* DH documentation says that a public key must be present if a
* private key is present.
*/
if (param_priv_key != NULL && param_pub_key == NULL)
return 0;
if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
goto err;
if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
goto err;
if (!DSA_set0_key(dsa, pub_key, priv_key))
goto err;
return 1;
err:
BN_clear_free(priv_key);
BN_free(pub_key);
return 0;
}
+1 -1
View File
@@ -32,7 +32,7 @@ int DSA_set_ex_data(DSA *d, int idx, void *arg)
return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
}
void *DSA_get_ex_data(DSA *d, int idx)
void *DSA_get_ex_data(const DSA *d, int idx)
{
return CRYPTO_get_ex_data(&d->ex_data, idx);
}
+2 -2
View File
@@ -51,9 +51,9 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
$ECASM
$ECASM ec_backend.c ecx_backend.c
SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \
ec_err.c ecdh_kdf.c eck_prn.c ec_evp_lib.c
ec_err.c ecdh_kdf.c eck_prn.c ec_ctrl.c
SOURCE[../../providers/libfips.a]=$COMMON
# Implementations are now spread across several libraries, so the defines
+6 -4
View File
@@ -5438,13 +5438,14 @@ static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
}
int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
const uint8_t public_key[32], const uint8_t private_key[32])
const uint8_t public_key[32], const uint8_t private_key[32],
OPENSSL_CTX *libctx, const char *propq)
{
uint8_t az[SHA512_DIGEST_LENGTH];
uint8_t nonce[SHA512_DIGEST_LENGTH];
ge_p3 R;
uint8_t hram[SHA512_DIGEST_LENGTH];
EVP_MD *sha512 = EVP_MD_fetch(NULL, SN_sha512, NULL);
EVP_MD *sha512 = EVP_MD_fetch(libctx, SN_sha512, propq);
EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();
unsigned int sz;
int res = 0;
@@ -5493,7 +5494,8 @@ err:
static const char allzeroes[15];
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32])
const uint8_t signature[64], const uint8_t public_key[32],
OPENSSL_CTX *libctx, const char *propq)
{
int i;
ge_p3 A;
@@ -5548,7 +5550,7 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
sha512 = EVP_MD_fetch(NULL, SN_sha512, NULL);
sha512 = EVP_MD_fetch(libctx, SN_sha512, propq);
if (sha512 == NULL)
return 0;
hash_ctx = EVP_MD_CTX_new();
-9
View File
@@ -10,15 +10,6 @@
# define OSSL_CRYPTO_EC_CURVE448_LOCAL_H
# include "curve448utils.h"
int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
size_t message_len, const uint8_t public_key[57],
const uint8_t private_key[57], const uint8_t *context,
size_t context_len);
int ED448_verify(OPENSSL_CTX *ctx, const uint8_t *message, size_t message_len,
const uint8_t signature[114], const uint8_t public_key[57],
const uint8_t *context, size_t context_len);
int ED448ph_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t hash[64],
const uint8_t public_key[57], const uint8_t private_key[57],
const uint8_t *context, size_t context_len);
+1
View File
@@ -12,6 +12,7 @@
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include "crypto/ecx.h"
#include "curve448_local.h"
#include "word.h"
#include "ed448.h"
+70 -28
View File
@@ -23,7 +23,7 @@
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include <openssl/core_names.h>
#include "internal/param_build.h"
#include "openssl/param_build.h"
#include "ec_local.h"
#ifndef OPENSSL_NO_CMS
@@ -611,7 +611,7 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl)
if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
return 0;
if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
return 0;
}
@@ -620,47 +620,65 @@ int ecparams_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl)
static
int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
const char *propq)
{
const EC_KEY *eckey = NULL;
const EC_GROUP *ecg = NULL;
unsigned char *pub_key_buf = NULL;
size_t pub_key_buflen;
OSSL_PARAM_BLD tmpl;
OSSL_PARAM_BLD *tmpl;
OSSL_PARAM *params = NULL;
const BIGNUM *priv_key = NULL;
const EC_POINT *pub_point = NULL;
int selection = 0;
int rv = 0;
BN_CTX *bnctx = NULL;
if (from == NULL
|| (eckey = from->pkey.ec) == NULL
|| (ecg = EC_KEY_get0_group(eckey)) == NULL)
return 0;
ossl_param_bld_init(&tmpl);
/*
* If the EC_KEY method is foreign, then we can't be sure of anything,
* and can therefore not export or pretend to export.
*/
if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL())
return 0;
tmpl = OSSL_PARAM_BLD_new();
if (tmpl == NULL)
return 0;
/* export the domain parameters */
if (!ecparams_to_params(eckey, &tmpl))
return 0;
if (!ecparams_to_params(eckey, tmpl))
goto err;
selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
priv_key = EC_KEY_get0_private_key(eckey);
pub_point = EC_KEY_get0_public_key(eckey);
/* public_key must be present, priv_key is optional */
if (pub_point == NULL)
return 0;
if (pub_point != NULL) {
/*
* EC_POINT_point2buf() can generate random numbers in some
* implementations so we need to ensure we use the correct libctx.
*/
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
goto err;
/* convert pub_point to a octet string according to the SECG standard */
if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
POINT_CONVERSION_COMPRESSED,
&pub_key_buf, NULL)) == 0)
return 0;
if (!ossl_param_bld_push_octet_string(&tmpl,
OSSL_PKEY_PARAM_PUB_KEY,
pub_key_buf,
pub_key_buflen))
goto err;
/* convert pub_point to a octet string according to the SECG standard */
if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
POINT_CONVERSION_COMPRESSED,
&pub_key_buf, bnctx)) == 0
|| !OSSL_PARAM_BLD_push_octet_string(tmpl,
OSSL_PKEY_PARAM_PUB_KEY,
pub_key_buf,
pub_key_buflen))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
}
if (priv_key != NULL) {
size_t sz;
@@ -705,10 +723,11 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
goto err;
sz = (ecbits + 7 ) / 8;
if (!ossl_param_bld_push_BN_pad(&tmpl,
if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
OSSL_PKEY_PARAM_PRIV_KEY,
priv_key, sz))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
/*
* The ECDH Cofactor Mode is defined only if the EC_KEY actually
@@ -719,24 +738,46 @@ int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
(EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
/* Export the ECDH_COFACTOR_MODE parameter */
if (!ossl_param_bld_push_int(&tmpl,
if (!OSSL_PARAM_BLD_push_int(tmpl,
OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
ecdh_cofactor_mode))
goto err;
selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
}
params = ossl_param_bld_to_param(&tmpl);
params = OSSL_PARAM_BLD_to_param(tmpl);
/* We export, the provider imports */
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
err:
ossl_param_bld_free(params);
OSSL_PARAM_BLD_free(tmpl);
OSSL_PARAM_BLD_free_params(params);
OPENSSL_free(pub_key_buf);
BN_CTX_free(bnctx);
return rv;
}
static int ec_pkey_import_from(const OSSL_PARAM params[], void *key)
{
EVP_PKEY *pkey = key;
EC_KEY *ec = EC_KEY_new();
if (ec == NULL) {
ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ec_key_domparams_fromdata(ec, params)
|| !ec_key_otherparams_fromdata(ec, params)
|| !ec_key_fromdata(ec, params, 1)
|| !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
EC_KEY_free(ec);
return 0;
}
return 1;
}
const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
EVP_PKEY_EC,
EVP_PKEY_EC,
@@ -782,7 +823,8 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
0, /* get_pub_key */
ec_pkey_dirty_cnt,
ec_pkey_export_to
ec_pkey_export_to,
ec_pkey_import_from
};
#if !defined(OPENSSL_NO_SM2)
+231
View File
@@ -0,0 +1,231 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include <openssl/objects.h>
#include <openssl/params.h>
#include "crypto/bn.h"
#include "crypto/ec.h"
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p)
{
const EC_GROUP *ecg = EC_KEY_get0_group(ec);
const BIGNUM *cofactor;
int mode;
if (!OSSL_PARAM_get_int(p, &mode))
return 0;
/*
* mode can be only 0 for disable, or 1 for enable here.
*
* This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
* also supports mode == -1 with the meaning of "reset to the default for
* the associated key".
*/
if (mode < 0 || mode > 1)
return 0;
if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
return 0;
/* ECDH cofactor mode has no effect if cofactor is 1 */
if (BN_is_one(cofactor))
return 1;
if (mode == 1)
EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
else if (mode == 0)
EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
return 1;
}
/*
* Callers of ec_key_fromdata MUST make sure that ec_key_params_fromdata has
* been called before!
*
* This function only gets the bare keypair, domain parameters and other
* parameters are treated separately, and domain parameters are required to
* define a keypair.
*/
int ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
{
const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL;
BN_CTX *ctx = NULL;
BIGNUM *priv_key = NULL;
unsigned char *pub_key = NULL;
size_t pub_key_len;
const EC_GROUP *ecg = NULL;
EC_POINT *pub_point = NULL;
int ok = 0;
ecg = EC_KEY_get0_group(ec);
if (ecg == NULL)
return 0;
param_pub_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
if (include_private)
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
ctx = BN_CTX_new_ex(ec_key_get_libctx(ec));
if (ctx == NULL)
goto err;
/* OpenSSL decree: If there's a private key, there must be a public key */
if (param_priv_key != NULL && param_pub_key == NULL)
goto err;
if (param_pub_key != NULL)
if (!OSSL_PARAM_get_octet_string(param_pub_key,
(void **)&pub_key, 0, &pub_key_len)
|| (pub_point = EC_POINT_new(ecg)) == NULL
|| !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx))
goto err;
if (param_priv_key != NULL && include_private) {
int fixed_words;
const BIGNUM *order;
/*
* Key import/export should never leak the bit length of the secret
* scalar in the key.
*
* For this reason, on export we use padded BIGNUMs with fixed length.
*
* When importing we also should make sure that, even if short lived,
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
* soon as possible, so that any processing of this BIGNUM might opt for
* constant time implementations in the backend.
*
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
* to preallocate the BIGNUM internal buffer to a fixed public size big
* enough that operations performed during the processing never trigger
* a realloc which would leak the size of the scalar through memory
* accesses.
*
* Fixed Length
* ------------
*
* The order of the large prime subgroup of the curve is our choice for
* a fixed public size, as that is generally the upper bound for
* generating a private key in EC cryptosystems and should fit all valid
* secret scalars.
*
* For padding on export we just use the bit length of the order
* converted to bytes (rounding up).
*
* For preallocating the BIGNUM storage we look at the number of "words"
* required for the internal representation of the order, and we
* preallocate 2 extra "words" in case any of the subsequent processing
* might temporarily overflow the order length.
*/
order = EC_GROUP_get0_order(ecg);
if (order == NULL || BN_is_zero(order))
goto err;
fixed_words = bn_get_top(order) + 2;
if ((priv_key = BN_secure_new()) == NULL)
goto err;
if (bn_wexpand(priv_key, fixed_words) == NULL)
goto err;
BN_set_flags(priv_key, BN_FLG_CONSTTIME);
if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
goto err;
}
if (priv_key != NULL
&& !EC_KEY_set_private_key(ec, priv_key))
goto err;
if (pub_point != NULL
&& !EC_KEY_set_public_key(ec, pub_point))
goto err;
ok = 1;
err:
BN_CTX_free(ctx);
BN_clear_free(priv_key);
OPENSSL_free(pub_key);
EC_POINT_free(pub_point);
return ok;
}
int ec_key_domparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *param_ec_name;
EC_GROUP *ecg = NULL;
char *curve_name = NULL;
int ok = 0;
if (ec == NULL)
return 0;
param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME);
if (param_ec_name == NULL) {
/* explicit parameters */
/*
* TODO(3.0): should we support explicit parameters curves?
*/
return 0;
} else {
/* named curve */
int curve_nid;
if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0)
|| curve_name == NULL
|| (curve_nid = ec_curve_name2nid(curve_name)) == NID_undef)
goto err;
if ((ecg = EC_GROUP_new_by_curve_name_ex(ec_key_get_libctx(ec),
curve_nid)) == NULL)
goto err;
}
if (!EC_KEY_set_group(ec, ecg))
goto err;
/*
* TODO(3.0): if the group has changed, should we invalidate the private and
* public key?
*/
ok = 1;
err:
OPENSSL_free(curve_name);
EC_GROUP_free(ecg);
return ok;
}
int ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
{
const OSSL_PARAM *p;
if (ec == NULL)
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p))
return 0;
return 1;
}
+10 -10
View File
@@ -19,27 +19,27 @@
int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only,
BN_CTX *ctx)
{
int nid = NID_undef;
#ifndef FIPS_MODE
int nid;
BN_CTX *new_ctx = NULL;
if (group == NULL) {
ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
return NID_undef;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
ctx = new_ctx = BN_CTX_new_ex(NULL);
if (ctx == NULL) {
ECerr(EC_F_EC_GROUP_CHECK_NAMED_CURVE, ERR_R_MALLOC_FAILURE);
goto err;
ECerr(0, ERR_R_MALLOC_FAILURE);
return NID_undef;
}
}
#endif
nid = ec_curve_nid_from_params(group, ctx);
if (nid > 0 && nist_only && EC_curve_nid2nist(nid) == NULL)
nid = NID_undef;
#ifndef FIPS_MODE
err:
BN_CTX_free(ctx);
#endif
BN_CTX_free(new_ctx);
return nid;
}
@@ -420,3 +420,69 @@ int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
return (int)ukmlen;
}
int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
const char *name)
{
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
OSSL_PARAM *p = params;
if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
if (name == NULL)
return -1;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
(char *)name, 0);
return EVP_PKEY_CTX_set_params(ctx, params);
}
int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
char *name, size_t namelen)
{
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
OSSL_PARAM *p = params;
if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
if (name == NULL)
return -1;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
name, namelen);
if (!EVP_PKEY_CTX_get_params(ctx, params))
return -1;
return 1;
}
#ifndef FIPS_MODE
int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
{
if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
/* Uses the same return values as EVP_PKEY_CTX_ctrl */
return -2;
}
/* Legacy: if key type not EC return error */
if (ctx->pmeth != NULL
&& EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC)
return -1;
if (ctx->op.keymgmt.genctx == NULL)
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
nid, NULL);
return EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, OBJ_nid2sn(nid));
}
#endif
+169 -122
View File
@@ -20,6 +20,7 @@
#include <openssl/obj_mac.h>
#include <openssl/opensslconf.h>
#include "internal/nelem.h"
#include "e_os.h" /* strcasecmp required by windows */
typedef struct {
int field_type, /* either NID_X9_62_prime_field or
@@ -2816,6 +2817,7 @@ static const struct {
#endif /* OPENSSL_NO_SM2 */
typedef struct _ec_list_element_st {
const char *name;
int nid;
const EC_CURVE_DATA *data;
const EC_METHOD *(*meth) (void);
@@ -2826,15 +2828,15 @@ typedef struct _ec_list_element_st {
static const ec_list_element curve_list[] = {
/* prime field curves */
/* secg curves */
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
{NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
"NIST/SECG curve over a 224 bit prime field"},
{"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h,
# if !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
EC_GFp_nistp224_method,
# else
{NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
"NIST/SECG curve over a 224 bit prime field"},
0,
# endif
"NIST/SECG curve over a 224 bit prime field"},
/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
{NID_secp384r1, &_EC_NIST_PRIME_384.h,
{"secp384r1", NID_secp384r1, &_EC_NIST_PRIME_384.h,
# if defined(S390X_EC_ASM)
EC_GFp_s390x_nistp384_method,
# else
@@ -2842,7 +2844,7 @@ static const ec_list_element curve_list[] = {
# endif
"NIST/SECG curve over a 384 bit prime field"},
{NID_secp521r1, &_EC_NIST_PRIME_521.h,
{"secp521r1", NID_secp521r1, &_EC_NIST_PRIME_521.h,
# if defined(S390X_EC_ASM)
EC_GFp_s390x_nistp521_method,
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
@@ -2853,9 +2855,9 @@ static const ec_list_element curve_list[] = {
"NIST/SECG curve over a 521 bit prime field"},
/* X9.62 curves */
{NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
{"prime192v1", NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
"NIST/X9.62/SECG curve over a 192 bit prime field"},
{NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
{"prime256v1", NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
# if defined(ECP_NISTZ256_ASM)
EC_GFp_nistz256_method,
# elif defined(S390X_EC_ASM)
@@ -2870,25 +2872,25 @@ static const ec_list_element curve_list[] = {
# ifndef OPENSSL_NO_EC2M
/* characteristic two field curves */
/* NIST/SECG curves */
{NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
{"sect163k1", NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
"NIST/SECG/WTLS curve over a 163 bit binary field"},
{NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
{"sect163r2", NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
"NIST/SECG curve over a 163 bit binary field"},
{NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
{"sect233k1", NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
{"sect233r1", NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
{"sect283k1", NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
"NIST/SECG curve over a 283 bit binary field"},
{NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
{"sect283r1", NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
"NIST/SECG curve over a 283 bit binary field"},
{NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
{"sect409k1", NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
"NIST/SECG curve over a 409 bit binary field"},
{NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
{"sect409r1", NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
"NIST/SECG curve over a 409 bit binary field"},
{NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
{"sect571k1", NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
"NIST/SECG curve over a 571 bit binary field"},
{NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
{"sect571r1", NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
"NIST/SECG curve over a 571 bit binary field"},
# endif
};
@@ -2898,43 +2900,43 @@ static const ec_list_element curve_list[] = {
static const ec_list_element curve_list[] = {
/* prime field curves */
/* secg curves */
{NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0,
{"secp112r1", NID_secp112r1, &_EC_SECG_PRIME_112R1.h, 0,
"SECG/WTLS curve over a 112 bit prime field"},
{NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0,
{"secp112r2", NID_secp112r2, &_EC_SECG_PRIME_112R2.h, 0,
"SECG curve over a 112 bit prime field"},
{NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0,
{"secp128r1", NID_secp128r1, &_EC_SECG_PRIME_128R1.h, 0,
"SECG curve over a 128 bit prime field"},
{NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0,
{"secp128r2", NID_secp128r2, &_EC_SECG_PRIME_128R2.h, 0,
"SECG curve over a 128 bit prime field"},
{NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0,
{"secp160k1", NID_secp160k1, &_EC_SECG_PRIME_160K1.h, 0,
"SECG curve over a 160 bit prime field"},
{NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0,
{"secp160r1", NID_secp160r1, &_EC_SECG_PRIME_160R1.h, 0,
"SECG curve over a 160 bit prime field"},
{NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0,
{"secp160r2", NID_secp160r2, &_EC_SECG_PRIME_160R2.h, 0,
"SECG/WTLS curve over a 160 bit prime field"},
/* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
{NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0,
{"secp192k1", NID_secp192k1, &_EC_SECG_PRIME_192K1.h, 0,
"SECG curve over a 192 bit prime field"},
{NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
{"secp224k1", NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
"SECG curve over a 224 bit prime field"},
# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
{NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
{"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
"NIST/SECG curve over a 224 bit prime field"},
# else
{NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
{"secp224r1", NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
"NIST/SECG curve over a 224 bit prime field"},
# endif
{NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
{"secp256k1", NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
"SECG curve over a 256 bit prime field"},
/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
{NID_secp384r1, &_EC_NIST_PRIME_384.h,
{"secp384r1", NID_secp384r1, &_EC_NIST_PRIME_384.h,
# if defined(S390X_EC_ASM)
EC_GFp_s390x_nistp384_method,
# else
0,
# endif
"NIST/SECG curve over a 384 bit prime field"},
{NID_secp521r1, &_EC_NIST_PRIME_521.h,
{"secp521r1", NID_secp521r1, &_EC_NIST_PRIME_521.h,
# if defined(S390X_EC_ASM)
EC_GFp_s390x_nistp521_method,
# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
@@ -2944,19 +2946,19 @@ static const ec_list_element curve_list[] = {
# endif
"NIST/SECG curve over a 521 bit prime field"},
/* X9.62 curves */
{NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
{"prime192v1", NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
"NIST/X9.62/SECG curve over a 192 bit prime field"},
{NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0,
{"prime192v2", NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0,
"X9.62 curve over a 192 bit prime field"},
{NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0,
{"prime192v3", NID_X9_62_prime192v3, &_EC_X9_62_PRIME_192V3.h, 0,
"X9.62 curve over a 192 bit prime field"},
{NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0,
{"prime239v1", NID_X9_62_prime239v1, &_EC_X9_62_PRIME_239V1.h, 0,
"X9.62 curve over a 239 bit prime field"},
{NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0,
{"prime239v2", NID_X9_62_prime239v2, &_EC_X9_62_PRIME_239V2.h, 0,
"X9.62 curve over a 239 bit prime field"},
{NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
{"prime239v3", NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
"X9.62 curve over a 239 bit prime field"},
{NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
{"prime256v1", NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
# if defined(ECP_NISTZ256_ASM)
EC_GFp_nistz256_method,
# elif defined(S390X_EC_ASM)
@@ -2970,144 +2972,144 @@ static const ec_list_element curve_list[] = {
# ifndef OPENSSL_NO_EC2M
/* characteristic two field curves */
/* NIST/SECG curves */
{NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0,
{"sect113r1", NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0,
"SECG curve over a 113 bit binary field"},
{NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0,
{"sect113r2", NID_sect113r2, &_EC_SECG_CHAR2_113R2.h, 0,
"SECG curve over a 113 bit binary field"},
{NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0,
{ "sect131r1", NID_sect131r1, &_EC_SECG_CHAR2_131R1.h, 0,
"SECG/WTLS curve over a 131 bit binary field"},
{NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0,
{ "sect131r2", NID_sect131r2, &_EC_SECG_CHAR2_131R2.h, 0,
"SECG curve over a 131 bit binary field"},
{NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
{"sect163k1", NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
"NIST/SECG/WTLS curve over a 163 bit binary field"},
{NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0,
{"sect163r1", NID_sect163r1, &_EC_SECG_CHAR2_163R1.h, 0,
"SECG curve over a 163 bit binary field"},
{NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
{"sect163r2", NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
"NIST/SECG curve over a 163 bit binary field"},
{NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0,
{"sect193r1", NID_sect193r1, &_EC_SECG_CHAR2_193R1.h, 0,
"SECG curve over a 193 bit binary field"},
{NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0,
{"sect193r2", NID_sect193r2, &_EC_SECG_CHAR2_193R2.h, 0,
"SECG curve over a 193 bit binary field"},
{NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
{"sect233k1", NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
{"sect233r1", NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0,
{"sect239k1", NID_sect239k1, &_EC_SECG_CHAR2_239K1.h, 0,
"SECG curve over a 239 bit binary field"},
{NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
{"sect283k1", NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
"NIST/SECG curve over a 283 bit binary field"},
{NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
{"sect283r1", NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
"NIST/SECG curve over a 283 bit binary field"},
{NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
{"sect409k1", NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
"NIST/SECG curve over a 409 bit binary field"},
{NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
{"sect409r1", NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
"NIST/SECG curve over a 409 bit binary field"},
{NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
{"sect571k1", NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
"NIST/SECG curve over a 571 bit binary field"},
{NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
{"sect571r1", NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
"NIST/SECG curve over a 571 bit binary field"},
/* X9.62 curves */
{NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0,
{"c2pnb163v1", NID_X9_62_c2pnb163v1, &_EC_X9_62_CHAR2_163V1.h, 0,
"X9.62 curve over a 163 bit binary field"},
{NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0,
{"c2pnb163v2", NID_X9_62_c2pnb163v2, &_EC_X9_62_CHAR2_163V2.h, 0,
"X9.62 curve over a 163 bit binary field"},
{NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0,
{"c2pnb163v3", NID_X9_62_c2pnb163v3, &_EC_X9_62_CHAR2_163V3.h, 0,
"X9.62 curve over a 163 bit binary field"},
{NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0,
{"c2pnb176v1", NID_X9_62_c2pnb176v1, &_EC_X9_62_CHAR2_176V1.h, 0,
"X9.62 curve over a 176 bit binary field"},
{NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0,
{"c2tnb191v1", NID_X9_62_c2tnb191v1, &_EC_X9_62_CHAR2_191V1.h, 0,
"X9.62 curve over a 191 bit binary field"},
{NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0,
{"c2tnb191v2", NID_X9_62_c2tnb191v2, &_EC_X9_62_CHAR2_191V2.h, 0,
"X9.62 curve over a 191 bit binary field"},
{NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0,
{"c2tnb191v3", NID_X9_62_c2tnb191v3, &_EC_X9_62_CHAR2_191V3.h, 0,
"X9.62 curve over a 191 bit binary field"},
{NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0,
{"c2pnb208w1", NID_X9_62_c2pnb208w1, &_EC_X9_62_CHAR2_208W1.h, 0,
"X9.62 curve over a 208 bit binary field"},
{NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0,
{"c2tnb239v1", NID_X9_62_c2tnb239v1, &_EC_X9_62_CHAR2_239V1.h, 0,
"X9.62 curve over a 239 bit binary field"},
{NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0,
{"c2tnb239v2", NID_X9_62_c2tnb239v2, &_EC_X9_62_CHAR2_239V2.h, 0,
"X9.62 curve over a 239 bit binary field"},
{NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0,
{"c2tnb239v3", NID_X9_62_c2tnb239v3, &_EC_X9_62_CHAR2_239V3.h, 0,
"X9.62 curve over a 239 bit binary field"},
{NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0,
{"c2pnb272w1", NID_X9_62_c2pnb272w1, &_EC_X9_62_CHAR2_272W1.h, 0,
"X9.62 curve over a 272 bit binary field"},
{NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0,
{"c2pnb304w1", NID_X9_62_c2pnb304w1, &_EC_X9_62_CHAR2_304W1.h, 0,
"X9.62 curve over a 304 bit binary field"},
{NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0,
{"c2tnb359v1", NID_X9_62_c2tnb359v1, &_EC_X9_62_CHAR2_359V1.h, 0,
"X9.62 curve over a 359 bit binary field"},
{NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0,
{"c2pnb368w1", NID_X9_62_c2pnb368w1, &_EC_X9_62_CHAR2_368W1.h, 0,
"X9.62 curve over a 368 bit binary field"},
{NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0,
{"c2tnb431r1", NID_X9_62_c2tnb431r1, &_EC_X9_62_CHAR2_431R1.h, 0,
"X9.62 curve over a 431 bit binary field"},
/*
* the WAP/WTLS curves [unlike SECG, spec has its own OIDs for curves
* from X9.62]
*/
{NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0,
{"wap-wsg-idm-ecid-wtls1", NID_wap_wsg_idm_ecid_wtls1, &_EC_WTLS_1.h, 0,
"WTLS curve over a 113 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0,
{"wap-wsg-idm-ecid-wtls3", NID_wap_wsg_idm_ecid_wtls3, &_EC_NIST_CHAR2_163K.h, 0,
"NIST/SECG/WTLS curve over a 163 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0,
{"wap-wsg-idm-ecid-wtls4", NID_wap_wsg_idm_ecid_wtls4, &_EC_SECG_CHAR2_113R1.h, 0,
"SECG curve over a 113 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
{"wap-wsg-idm-ecid-wtls5", NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
"X9.62 curve over a 163 bit binary field"},
# endif
{NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
{"wap-wsg-idm-ecid-wtls6", NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
"SECG/WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0,
{"wap-wsg-idm-ecid-wtls7", NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0,
"SECG/WTLS curve over a 160 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0,
{"wap-wsg-idm-ecid-wtls8", NID_wap_wsg_idm_ecid_wtls8, &_EC_WTLS_8.h, 0,
"WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
{"wap-wsg-idm-ecid-wtls9", NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
"WTLS curve over a 160 bit prime field"},
# ifndef OPENSSL_NO_EC2M
{NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
{"wap-wsg-idm-ecid-wtls10", NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
{"wap-wsg-idm-ecid-wtls11", NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"},
# endif
{NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
{"wap-wsg-idm-ecid-wtls12", NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
"WTLS curve over a 224 bit prime field"},
# ifndef OPENSSL_NO_EC2M
/* IPSec curves */
{NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
{"Oakley-EC2N-3", NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
"\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
"\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
{NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
{"Oakley-EC2N-4", NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
"\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
"\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
# endif
/* brainpool curves */
{NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
{"brainpoolP160r1", NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
"RFC 5639 curve over a 160 bit prime field"},
{NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0,
{"brainpoolP160t1", NID_brainpoolP160t1, &_EC_brainpoolP160t1.h, 0,
"RFC 5639 curve over a 160 bit prime field"},
{NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0,
{"brainpoolP192r1", NID_brainpoolP192r1, &_EC_brainpoolP192r1.h, 0,
"RFC 5639 curve over a 192 bit prime field"},
{NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0,
{"brainpoolP192t1", NID_brainpoolP192t1, &_EC_brainpoolP192t1.h, 0,
"RFC 5639 curve over a 192 bit prime field"},
{NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0,
{"brainpoolP224r1", NID_brainpoolP224r1, &_EC_brainpoolP224r1.h, 0,
"RFC 5639 curve over a 224 bit prime field"},
{NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0,
{"brainpoolP224t1", NID_brainpoolP224t1, &_EC_brainpoolP224t1.h, 0,
"RFC 5639 curve over a 224 bit prime field"},
{NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0,
{"brainpoolP256r1", NID_brainpoolP256r1, &_EC_brainpoolP256r1.h, 0,
"RFC 5639 curve over a 256 bit prime field"},
{NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0,
{"brainpoolP256t1", NID_brainpoolP256t1, &_EC_brainpoolP256t1.h, 0,
"RFC 5639 curve over a 256 bit prime field"},
{NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0,
{"brainpoolP320r1", NID_brainpoolP320r1, &_EC_brainpoolP320r1.h, 0,
"RFC 5639 curve over a 320 bit prime field"},
{NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0,
{"brainpoolP320t1", NID_brainpoolP320t1, &_EC_brainpoolP320t1.h, 0,
"RFC 5639 curve over a 320 bit prime field"},
{NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0,
{"brainpoolP384r1", NID_brainpoolP384r1, &_EC_brainpoolP384r1.h, 0,
"RFC 5639 curve over a 384 bit prime field"},
{NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0,
{"brainpoolP384t1", NID_brainpoolP384t1, &_EC_brainpoolP384t1.h, 0,
"RFC 5639 curve over a 384 bit prime field"},
{NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0,
{"brainpoolP512r1", NID_brainpoolP512r1, &_EC_brainpoolP512r1.h, 0,
"RFC 5639 curve over a 512 bit prime field"},
{NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
{"brainpoolP512t1", NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
"RFC 5639 curve over a 512 bit prime field"},
# ifndef OPENSSL_NO_SM2
{NID_sm2, &_EC_sm2p256v1.h, 0,
{"SM2", NID_sm2, &_EC_sm2p256v1.h, 0,
"SM2 curve over a 256 bit prime field"},
# endif
};
@@ -3115,6 +3117,68 @@ static const ec_list_element curve_list[] = {
#define curve_list_length OSSL_NELEM(curve_list)
static const ec_list_element *ec_curve_nid2curve(int nid)
{
size_t i;
if (nid <= 0)
return NULL;
for (i = 0; i < curve_list_length; i++) {
if (curve_list[i].nid == nid)
return &curve_list[i];
}
return NULL;
}
static const ec_list_element *ec_curve_name2curve(const char *name)
{
size_t i;
for (i = 0; i < curve_list_length; i++) {
if (strcasecmp(curve_list[i].name, name) == 0)
return &curve_list[i];
}
return NULL;
}
const char *ec_curve_nid2name(int nid)
{
/*
* TODO(3.0) Figure out if we should try to find the nid with
* EC_curve_nid2nist() first, i.e. make it a priority to return
* NIST names if there is one for the NID. This is related to
* the TODO comment in ec_curve_name2nid().
*/
const ec_list_element *curve = ec_curve_nid2curve(nid);
if (curve != NULL)
return curve->name;
return NULL;
}
int ec_curve_name2nid(const char *name)
{
const ec_list_element *curve = NULL;
int nid;
if ((nid = EC_curve_nist2nid(name)) != NID_undef)
return nid;
#ifndef FIPS_MODE
/*
* TODO(3.0) Figure out if we can use other names than the NIST names
* ("B-163", "K-163" & "P-192") in the FIPS module, or if other names
* are allowed as well as long as they lead to the same curve data.
* If only the NIST names are allowed in the FIPS module, we should
* move '#endif' to just before 'return NID_undef'.
*/
#endif
if ((curve = ec_curve_name2curve(name)) != NULL)
return curve->nid;
return NID_undef;
}
static EC_GROUP *ec_group_new_from_data(OPENSSL_CTX *libctx,
const ec_list_element curve)
{
@@ -3226,28 +3290,11 @@ static EC_GROUP *ec_group_new_from_data(OPENSSL_CTX *libctx,
EC_GROUP *EC_GROUP_new_by_curve_name_ex(OPENSSL_CTX *libctx, int nid)
{
size_t i;
EC_GROUP *ret = NULL;
const ec_list_element *curve;
if (nid <= 0)
return NULL;
#ifdef FIPS_MODE
/*
* Only use approved NIST curves in FIPS.
* NOTE: "B-163", "K-163" & "P-192" can only be used for legacy use
* (i.e- ECDSA signature verification).
*/
if (EC_curve_nid2nist(nid) == NULL)
return NULL;
#endif /* FIPS_MODE */
for (i = 0; i < curve_list_length; i++)
if (curve_list[i].nid == nid) {
ret = ec_group_new_from_data(libctx, curve_list[i]);
break;
}
if (ret == NULL) {
if ((curve = ec_curve_nid2curve(nid)) == NULL
|| (ret = ec_group_new_from_data(libctx, *curve)) == NULL) {
ECerr(EC_F_EC_GROUP_NEW_BY_CURVE_NAME_EX, EC_R_UNKNOWN_GROUP);
return NULL;
}
+126 -63
View File
@@ -417,6 +417,120 @@ err:
return ret;
}
/*
* ECC Key validation as specified in SP800-56A R3.
* Section 5.6.2.3.3 ECC Full Public-Key Validation.
*/
int ec_key_public_check(const EC_KEY *eckey, BN_CTX *ctx)
{
int ret = 0;
EC_POINT *point = NULL;
const BIGNUM *order = NULL;
if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* 5.6.2.3.3 (Step 1): Q != infinity */
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
ECerr(0, EC_R_POINT_AT_INFINITY);
return 0;
}
point = EC_POINT_new(eckey->group);
if (point == NULL)
return 0;
/* 5.6.2.3.3 (Step 2) Test if the public key is in range */
if (!ec_key_public_range_check(ctx, eckey)) {
ECerr(0, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
/* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */
if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
ECerr(0, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
order = eckey->group->order;
if (BN_is_zero(order)) {
ECerr(0, EC_R_INVALID_GROUP_ORDER);
goto err;
}
/* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */
if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
ECerr(0, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_is_at_infinity(eckey->group, point)) {
ECerr(0, EC_R_WRONG_ORDER);
goto err;
}
ret = 1;
err:
EC_POINT_free(point);
return ret;
}
/*
* ECC Key validation as specified in SP800-56A R3.
* Section 5.6.2.1.2 Owner Assurance of Private-Key Validity
* The private key is in the range [1, order-1]
*/
int ec_key_private_check(const EC_KEY *eckey)
{
if (eckey == NULL || eckey->group == NULL || eckey->priv_key == NULL) {
ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (BN_cmp(eckey->priv_key, BN_value_one()) < 0
|| BN_cmp(eckey->priv_key, eckey->group->order) >= 0) {
ECerr(0, EC_R_INVALID_PRIVATE_KEY);
return 0;
}
return 1;
}
/*
* ECC Key validation as specified in SP800-56A R3.
* Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b)
* Check if generator * priv_key = pub_key
*/
int ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx)
{
int ret = 0;
EC_POINT *point = NULL;
if (eckey == NULL
|| eckey->group == NULL
|| eckey->pub_key == NULL
|| eckey->priv_key == NULL) {
ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
point = EC_POINT_new(eckey->group);
if (point == NULL)
goto err;
if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL, NULL, ctx)) {
ECerr(0, ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
ECerr(0, EC_R_INVALID_PRIVATE_KEY);
goto err;
}
ret = 1;
err:
EC_POINT_free(point);
return ret;
}
/*
* ECC Key validation as specified in SP800-56A R3.
* Section 5.6.2.3.3 ECC Full Public-Key Validation
@@ -431,81 +545,25 @@ int ec_key_simple_check_key(const EC_KEY *eckey)
{
int ok = 0;
BN_CTX *ctx = NULL;
const BIGNUM *order = NULL;
EC_POINT *point = NULL;
if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_PASSED_NULL_PARAMETER);
if (eckey == NULL) {
ECerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
/* 5.6.2.3.3 (Step 1): Q != infinity */
if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_AT_INFINITY);
goto err;
}
if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL)
goto err;
return 0;
if ((point = EC_POINT_new(eckey->group)) == NULL)
if (!ec_key_public_check(eckey, ctx))
goto err;
/* 5.6.2.3.3 (Step 2) Test if the public key is in range */
if (!ec_key_public_range_check(ctx, eckey)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
/* 5.6.2.3.3 (Step 3) is the pub_key on the elliptic curve */
if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
order = eckey->group->order;
if (BN_is_zero(order)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_GROUP_ORDER);
goto err;
}
/* 5.6.2.3.3 (Step 4) : pub_key * order is the point at infinity. */
if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_is_at_infinity(eckey->group, point)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
goto err;
}
if (eckey->priv_key != NULL) {
/*
* 5.6.2.1.2 Owner Assurance of Private-Key Validity
* The private key is in the range [1, order-1]
*/
if (BN_cmp(eckey->priv_key, BN_value_one()) < 0
|| BN_cmp(eckey->priv_key, order) >= 0) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_WRONG_ORDER);
if (!ec_key_private_check(eckey)
|| !ec_key_pairwise_check(eckey, ctx))
goto err;
}
/*
* Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency (b)
* Check if generator * priv_key = pub_key
*/
if (!EC_POINT_mul(eckey->group, point, eckey->priv_key,
NULL, NULL, ctx)) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, ERR_R_EC_LIB);
goto err;
}
if (EC_POINT_cmp(eckey->group, point, eckey->pub_key, ctx) != 0) {
ECerr(EC_F_EC_KEY_SIMPLE_CHECK_KEY, EC_R_INVALID_PRIVATE_KEY);
goto err;
}
}
ok = 1;
err:
err:
BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
}
@@ -569,6 +627,11 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
}
OPENSSL_CTX *ec_key_get_libctx(const EC_KEY *key)
{
return key->libctx;
}
const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key)
{
return key->group;
+29 -23
View File
@@ -599,12 +599,7 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
#ifndef FIPS_MODE
BN_CTX *ctx_new = NULL;
if (ctx == NULL)
ctx_new = ctx = BN_CTX_new();
#endif
if (ctx == NULL)
return -1;
/* compare the field types */
if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
@@ -617,6 +612,13 @@ int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
return 0;
#ifndef FIPS_MODE
if (ctx == NULL)
ctx_new = ctx = BN_CTX_new();
#endif
if (ctx == NULL)
return -1;
BN_CTX_start(ctx);
a1 = BN_CTX_get(ctx);
a2 = BN_CTX_get(ctx);
@@ -1047,7 +1049,24 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t i = 0;
#ifndef FIPS_MODE
BN_CTX *new_ctx = NULL;
#endif
if (!ec_point_is_compat(r, group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (scalar == NULL && num == 0)
return EC_POINT_set_to_infinity(group, r);
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
#ifndef FIPS_MODE
if (ctx == NULL)
ctx = new_ctx = BN_CTX_secure_new();
#endif
@@ -1056,21 +1075,6 @@ int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
return 0;
}
if ((scalar == NULL) && (num == 0)) {
return EC_POINT_set_to_infinity(group, r);
}
if (!ec_point_is_compat(r, group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
if (group->meth->mul != NULL)
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
else
@@ -1183,16 +1187,18 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
int ret = 0;
#ifndef FIPS_MODE
BN_CTX *new_ctx = NULL;
#endif
if (group->mont_data == NULL)
return 0;
#ifndef FIPS_MODE
if (ctx == NULL)
ctx = new_ctx = BN_CTX_secure_new();
#endif
if (ctx == NULL)
return 0;
if (group->mont_data == NULL)
goto err;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
-4
View File
@@ -679,10 +679,6 @@ ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
const uint8_t public_key[32], const uint8_t private_key[32]);
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32]);
void ED25519_public_from_private(uint8_t out_public_key[32],
const uint8_t private_key[32]);
+18 -11
View File
@@ -266,17 +266,10 @@ int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
goto err;
}
/*-
* Apply coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
* ec_point_blind_coordinates() returns 0 in case of errors or 1 on
* success or if coordinate blinding is not implemented for this
* group.
*/
if (!ec_point_blind_coordinates(group, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE);
goto err;
/* ensure input point is in affine coords for ladder step efficiency */
if (!p->Z_is_one && !EC_POINT_make_affine(group, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
goto err;
}
/* Initialize the Montgomery ladder */
@@ -753,6 +746,20 @@ int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
if (r_is_at_infinity) {
if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
goto err;
/*-
* Apply coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
* ec_point_blind_coordinates() returns 0 in case of errors or 1 on
* success or if coordinate blinding is not implemented for this
* group.
*/
if (!ec_point_blind_coordinates(group, r, ctx)) {
ECerr(EC_F_EC_WNAF_MUL, EC_R_POINT_COORDINATES_BLIND_FAILURE);
goto err;
}
r_is_at_infinity = 0;
} else {
if (!EC_POINT_add
+168 -139
View File
@@ -1381,6 +1381,7 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
* Computes the multiplicative inverse of a in GF(p), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* Since we don't have a Mont structure here, SCA hardening is with blinding.
* NB: "a" must be in _decoded_ form. (i.e. field_decode must precede.)
*/
int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx)
@@ -1441,112 +1442,133 @@ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
temp = BN_CTX_get(ctx);
if (temp == NULL) {
ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE);
goto err;
goto end;
}
/* make sure lambda is not zero */
/*-
* Make sure lambda is not zero.
* If the RNG fails, we cannot blind but nevertheless want
* code to continue smoothly and not clobber the error stack.
*/
do {
if (!BN_priv_rand_range_ex(lambda, group->field, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB);
goto err;
ERR_set_mark();
ret = BN_priv_rand_range_ex(lambda, group->field, ctx);
ERR_pop_to_mark();
if (ret == 0) {
ret = 1;
goto end;
}
} while (BN_is_zero(lambda));
/* if field_encode defined convert between representations */
if (group->meth->field_encode != NULL
&& !group->meth->field_encode(group, lambda, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->Z, p->Z, lambda, ctx))
goto err;
if (!group->meth->field_sqr(group, temp, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->X, p->X, temp, ctx))
goto err;
if (!group->meth->field_mul(group, temp, temp, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->Y, p->Y, temp, ctx))
goto err;
p->Z_is_one = 0;
if ((group->meth->field_encode != NULL
&& !group->meth->field_encode(group, lambda, lambda, ctx))
|| !group->meth->field_mul(group, p->Z, p->Z, lambda, ctx)
|| !group->meth->field_sqr(group, temp, lambda, ctx)
|| !group->meth->field_mul(group, p->X, p->X, temp, ctx)
|| !group->meth->field_mul(group, temp, temp, lambda, ctx)
|| !group->meth->field_mul(group, p->Y, p->Y, temp, ctx))
goto end;
p->Z_is_one = 0;
ret = 1;
err:
end:
BN_CTX_end(ctx);
return ret;
}
/*-
* Set s := p, r := 2p.
* Input:
* - p: affine coordinates
*
* Output:
* - s := p, r := 2p: blinded projective (homogeneous) coordinates
*
* For doubling we use Formula 3 from Izu-Takagi "A fast parallel elliptic curve
* multiplication resistant against side channel attacks" appendix, as described
* at
* multiplication resistant against side channel attacks" appendix, described at
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#doubling-dbl-2002-it-2
* simplified for Z1=1.
*
* The input point p will be in randomized Jacobian projective coords:
* x = X/Z**2, y=Y/Z**3
*
* The output points p, s, and r are converted to standard (homogeneous)
* projective coords:
* x = X/Z, y=Y/Z
* Blinding uses the equivalence relation (\lambda X, \lambda Y, \lambda Z)
* for any non-zero \lambda that holds for projective (homogeneous) coords.
*/
int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
BIGNUM *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
BIGNUM *t1, *t2, *t3, *t4, *t5 = NULL;
t1 = r->Z;
t2 = r->Y;
t1 = s->Z;
t2 = r->Z;
t3 = s->X;
t4 = r->X;
t5 = s->Y;
t6 = s->Z;
/* convert p: (X,Y,Z) -> (XZ,Y,Z**3) */
if (!group->meth->field_mul(group, p->X, p->X, p->Z, ctx)
|| !group->meth->field_sqr(group, t1, p->Z, ctx)
|| !group->meth->field_mul(group, p->Z, p->Z, t1, ctx)
/* r := 2p */
|| !group->meth->field_sqr(group, t2, p->X, ctx)
|| !group->meth->field_sqr(group, t3, p->Z, ctx)
|| !group->meth->field_mul(group, t4, t3, group->a, ctx)
|| !BN_mod_sub_quick(t5, t2, t4, group->field)
|| !BN_mod_add_quick(t2, t2, t4, group->field)
|| !group->meth->field_sqr(group, t5, t5, ctx)
|| !group->meth->field_mul(group, t6, t3, group->b, ctx)
|| !group->meth->field_mul(group, t1, p->X, p->Z, ctx)
|| !group->meth->field_mul(group, t4, t1, t6, ctx)
|| !BN_mod_lshift_quick(t4, t4, 3, group->field)
if (!p->Z_is_one /* r := 2p */
|| !group->meth->field_sqr(group, t3, p->X, ctx)
|| !BN_mod_sub_quick(t4, t3, group->a, group->field)
|| !group->meth->field_sqr(group, t4, t4, ctx)
|| !group->meth->field_mul(group, t5, p->X, group->b, ctx)
|| !BN_mod_lshift_quick(t5, t5, 3, group->field)
/* r->X coord output */
|| !BN_mod_sub_quick(r->X, t5, t4, group->field)
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|| !group->meth->field_mul(group, t2, t3, t6, ctx)
|| !BN_mod_add_quick(t1, t1, t2, group->field)
|| !BN_mod_sub_quick(r->X, t4, t5, group->field)
|| !BN_mod_add_quick(t1, t3, group->a, group->field)
|| !group->meth->field_mul(group, t2, p->X, t1, ctx)
|| !BN_mod_add_quick(t2, group->b, t2, group->field)
/* r->Z coord output */
|| !BN_mod_lshift_quick(r->Z, t1, 2, group->field)
|| !EC_POINT_copy(s, p))
|| !BN_mod_lshift_quick(r->Z, t2, 2, group->field))
return 0;
/* make sure lambda (r->Y here for storage) is not zero */
do {
if (!BN_priv_rand_range_ex(r->Y, group->field, ctx))
return 0;
} while (BN_is_zero(r->Y));
/* make sure lambda (s->Z here for storage) is not zero */
do {
if (!BN_priv_rand_range_ex(s->Z, group->field, ctx))
return 0;
} while (BN_is_zero(s->Z));
/* if field_encode defined convert between representations */
if (group->meth->field_encode != NULL
&& (!group->meth->field_encode(group, r->Y, r->Y, ctx)
|| !group->meth->field_encode(group, s->Z, s->Z, ctx)))
return 0;
/* blind r and s independently */
if (!group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
|| !group->meth->field_mul(group, r->X, r->X, r->Y, ctx)
|| !group->meth->field_mul(group, s->X, p->X, s->Z, ctx)) /* s := p */
return 0;
r->Z_is_one = 0;
s->Z_is_one = 0;
p->Z_is_one = 0;
return 1;
}
/*-
* Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi
* Input:
* - s, r: projective (homogeneous) coordinates
* - p: affine coordinates
*
* Output:
* - s := r + s, r := 2r: projective (homogeneous) coordinates
*
* Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi
* "A fast parallel elliptic curve multiplication resistant against side channel
* attacks", as described at
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-ladd-2002-it-4
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-mladd-2002-it-4
*/
int ec_GFp_simple_ladder_step(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7 = NULL;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
BN_CTX_start(ctx);
t0 = BN_CTX_get(ctx);
@@ -1556,50 +1578,47 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group,
t4 = BN_CTX_get(ctx);
t5 = BN_CTX_get(ctx);
t6 = BN_CTX_get(ctx);
t7 = BN_CTX_get(ctx);
if (t7 == NULL
|| !group->meth->field_mul(group, t0, r->X, s->X, ctx)
|| !group->meth->field_mul(group, t1, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t2, r->X, s->Z, ctx)
if (t6 == NULL
|| !group->meth->field_mul(group, t6, r->X, s->X, ctx)
|| !group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t4, r->X, s->Z, ctx)
|| !group->meth->field_mul(group, t3, r->Z, s->X, ctx)
|| !group->meth->field_mul(group, t4, group->a, t1, ctx)
|| !BN_mod_add_quick(t0, t0, t4, group->field)
|| !BN_mod_add_quick(t4, t3, t2, group->field)
|| !group->meth->field_mul(group, t0, t4, t0, ctx)
|| !group->meth->field_sqr(group, t1, t1, ctx)
|| !BN_mod_lshift_quick(t7, group->b, 2, group->field)
|| !group->meth->field_mul(group, t1, t7, t1, ctx)
|| !BN_mod_lshift1_quick(t0, t0, group->field)
|| !BN_mod_add_quick(t0, t1, t0, group->field)
|| !BN_mod_sub_quick(t1, t2, t3, group->field)
|| !group->meth->field_sqr(group, t1, t1, ctx)
|| !group->meth->field_mul(group, t3, t1, p->X, ctx)
|| !group->meth->field_mul(group, t0, p->Z, t0, ctx)
/* s->X coord output */
|| !BN_mod_sub_quick(s->X, t0, t3, group->field)
/* s->Z coord output */
|| !group->meth->field_mul(group, s->Z, p->Z, t1, ctx)
|| !group->meth->field_sqr(group, t3, r->X, ctx)
|| !group->meth->field_sqr(group, t2, r->Z, ctx)
|| !group->meth->field_mul(group, t4, t2, group->a, ctx)
|| !BN_mod_add_quick(t5, r->X, r->Z, group->field)
|| !group->meth->field_sqr(group, t5, t5, ctx)
|| !BN_mod_sub_quick(t5, t5, t3, group->field)
|| !BN_mod_sub_quick(t5, t5, t2, group->field)
|| !BN_mod_sub_quick(t6, t3, t4, group->field)
|| !group->meth->field_sqr(group, t6, t6, ctx)
|| !group->meth->field_mul(group, t0, t2, t5, ctx)
|| !group->meth->field_mul(group, t0, t7, t0, ctx)
/* r->X coord output */
|| !BN_mod_sub_quick(r->X, t6, t0, group->field)
|| !group->meth->field_mul(group, t5, group->a, t0, ctx)
|| !BN_mod_add_quick(t5, t6, t5, group->field)
|| !BN_mod_add_quick(t6, t3, t4, group->field)
|| !group->meth->field_sqr(group, t3, t2, ctx)
|| !group->meth->field_mul(group, t7, t3, t7, ctx)
|| !group->meth->field_mul(group, t5, t5, t6, ctx)
|| !group->meth->field_mul(group, t5, t6, t5, ctx)
|| !group->meth->field_sqr(group, t0, t0, ctx)
|| !BN_mod_lshift_quick(t2, group->b, 2, group->field)
|| !group->meth->field_mul(group, t0, t2, t0, ctx)
|| !BN_mod_lshift1_quick(t5, t5, group->field)
|| !BN_mod_sub_quick(t3, t4, t3, group->field)
/* s->Z coord output */
|| !group->meth->field_sqr(group, s->Z, t3, ctx)
|| !group->meth->field_mul(group, t4, s->Z, p->X, ctx)
|| !BN_mod_add_quick(t0, t0, t5, group->field)
/* s->X coord output */
|| !BN_mod_sub_quick(s->X, t0, t4, group->field)
|| !group->meth->field_sqr(group, t4, r->X, ctx)
|| !group->meth->field_sqr(group, t5, r->Z, ctx)
|| !group->meth->field_mul(group, t6, t5, group->a, ctx)
|| !BN_mod_add_quick(t1, r->X, r->Z, group->field)
|| !group->meth->field_sqr(group, t1, t1, ctx)
|| !BN_mod_sub_quick(t1, t1, t4, group->field)
|| !BN_mod_sub_quick(t1, t1, t5, group->field)
|| !BN_mod_sub_quick(t3, t4, t6, group->field)
|| !group->meth->field_sqr(group, t3, t3, ctx)
|| !group->meth->field_mul(group, t0, t5, t1, ctx)
|| !group->meth->field_mul(group, t0, t2, t0, ctx)
/* r->X coord output */
|| !BN_mod_sub_quick(r->X, t3, t0, group->field)
|| !BN_mod_add_quick(t3, t4, t6, group->field)
|| !group->meth->field_sqr(group, t4, t5, ctx)
|| !group->meth->field_mul(group, t4, t4, t2, ctx)
|| !group->meth->field_mul(group, t1, t1, t3, ctx)
|| !BN_mod_lshift1_quick(t1, t1, group->field)
/* r->Z coord output */
|| !BN_mod_add_quick(r->Z, t7, t5, group->field))
|| !BN_mod_add_quick(r->Z, t4, t1, group->field))
goto err;
ret = 1;
@@ -1610,17 +1629,23 @@ int ec_GFp_simple_ladder_step(const EC_GROUP *group,
}
/*-
* Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass
* Elliptic Curves and Side-Channel Attacks", modified to work in projective
* coordinates and return r in Jacobian projective coordinates.
* Input:
* - s, r: projective (homogeneous) coordinates
* - p: affine coordinates
*
* X4 = two*Y1*X2*Z3*Z2*Z1;
* Y4 = two*b*Z3*SQR(Z2*Z1) + Z3*(a*Z2*Z1+X1*X2)*(X1*Z2+X2*Z1) - X3*SQR(X1*Z2-X2*Z1);
* Z4 = two*Y1*Z3*SQR(Z2)*Z1;
* Output:
* - r := (x,y): affine coordinates
*
* Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass
* Elliptic Curves and Side-Channel Attacks", modified to work in mixed
* projective coords, i.e. p is affine and (r,s) in projective (homogeneous)
* coords, and return r in affine coordinates.
*
* X4 = two*Y1*X2*Z3*Z2;
* Y4 = two*b*Z3*SQR(Z2) + Z3*(a*Z2+X1*X2)*(X1*Z2+X2) - X3*SQR(X1*Z2-X2);
* Z4 = two*Y1*Z3*SQR(Z2);
*
* Z4 != 0 because:
* - Z1==0 implies p is at infinity, which would have caused an early exit in
* the caller;
* - Z2==0 implies r is at infinity (handled by the BN_is_zero(r->Z) branch);
* - Z3==0 implies s is at infinity (handled by the BN_is_zero(s->Z) branch);
* - Y1==0 implies p has order 2, so either r or s are infinity and handled by
@@ -1637,11 +1662,7 @@ int ec_GFp_simple_ladder_post(const EC_GROUP *group,
return EC_POINT_set_to_infinity(group, r);
if (BN_is_zero(s->Z)) {
/* (X,Y,Z) -> (XZ,YZ**2,Z) */
if (!group->meth->field_mul(group, r->X, p->X, p->Z, ctx)
|| !group->meth->field_sqr(group, r->Z, p->Z, ctx)
|| !group->meth->field_mul(group, r->Y, p->Y, r->Z, ctx)
|| !BN_copy(r->Z, p->Z)
if (!EC_POINT_copy(r, p)
|| !EC_POINT_invert(group, r, ctx))
return 0;
return 1;
@@ -1657,38 +1678,46 @@ int ec_GFp_simple_ladder_post(const EC_GROUP *group,
t6 = BN_CTX_get(ctx);
if (t6 == NULL
|| !BN_mod_lshift1_quick(t0, p->Y, group->field)
|| !group->meth->field_mul(group, t1, r->X, p->Z, ctx)
|| !group->meth->field_mul(group, t2, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t2, t1, t2, ctx)
|| !group->meth->field_mul(group, t3, t2, t0, ctx)
|| !group->meth->field_mul(group, t2, r->Z, p->Z, ctx)
|| !group->meth->field_sqr(group, t4, t2, ctx)
|| !BN_mod_lshift1_quick(t5, group->b, group->field)
|| !group->meth->field_mul(group, t4, t4, t5, ctx)
|| !group->meth->field_mul(group, t6, t2, group->a, ctx)
|| !group->meth->field_mul(group, t5, r->X, p->X, ctx)
|| !BN_mod_add_quick(t5, t6, t5, group->field)
|| !group->meth->field_mul(group, t6, r->Z, p->X, ctx)
|| !BN_mod_add_quick(t2, t6, t1, group->field)
|| !group->meth->field_mul(group, t5, t5, t2, ctx)
|| !BN_mod_sub_quick(t6, t6, t1, group->field)
|| !group->meth->field_sqr(group, t6, t6, ctx)
|| !group->meth->field_mul(group, t6, t6, s->X, ctx)
|| !BN_mod_add_quick(t4, t5, t4, group->field)
|| !group->meth->field_mul(group, t4, t4, s->Z, ctx)
|| !BN_mod_sub_quick(t4, t4, t6, group->field)
|| !group->meth->field_sqr(group, t5, r->Z, ctx)
|| !group->meth->field_mul(group, r->Z, p->Z, s->Z, ctx)
|| !group->meth->field_mul(group, r->Z, t5, r->Z, ctx)
|| !group->meth->field_mul(group, r->Z, r->Z, t0, ctx)
/* t3 := X, t4 := Y */
/* (X,Y,Z) -> (XZ,YZ**2,Z) */
|| !group->meth->field_mul(group, r->X, t3, r->Z, ctx)
|| !BN_mod_lshift1_quick(t4, p->Y, group->field)
|| !group->meth->field_mul(group, t6, r->X, t4, ctx)
|| !group->meth->field_mul(group, t6, s->Z, t6, ctx)
|| !group->meth->field_mul(group, t5, r->Z, t6, ctx)
|| !BN_mod_lshift1_quick(t1, group->b, group->field)
|| !group->meth->field_mul(group, t1, s->Z, t1, ctx)
|| !group->meth->field_sqr(group, t3, r->Z, ctx)
|| !group->meth->field_mul(group, r->Y, t4, t3, ctx))
|| !group->meth->field_mul(group, t2, t3, t1, ctx)
|| !group->meth->field_mul(group, t6, r->Z, group->a, ctx)
|| !group->meth->field_mul(group, t1, p->X, r->X, ctx)
|| !BN_mod_add_quick(t1, t1, t6, group->field)
|| !group->meth->field_mul(group, t1, s->Z, t1, ctx)
|| !group->meth->field_mul(group, t0, p->X, r->Z, ctx)
|| !BN_mod_add_quick(t6, r->X, t0, group->field)
|| !group->meth->field_mul(group, t6, t6, t1, ctx)
|| !BN_mod_add_quick(t6, t6, t2, group->field)
|| !BN_mod_sub_quick(t0, t0, r->X, group->field)
|| !group->meth->field_sqr(group, t0, t0, ctx)
|| !group->meth->field_mul(group, t0, t0, s->X, ctx)
|| !BN_mod_sub_quick(t0, t6, t0, group->field)
|| !group->meth->field_mul(group, t1, s->Z, t4, ctx)
|| !group->meth->field_mul(group, t1, t3, t1, ctx)
|| (group->meth->field_decode != NULL
&& !group->meth->field_decode(group, t1, t1, ctx))
|| !group->meth->field_inv(group, t1, t1, ctx)
|| (group->meth->field_encode != NULL
&& !group->meth->field_encode(group, t1, t1, ctx))
|| !group->meth->field_mul(group, r->X, t5, t1, ctx)
|| !group->meth->field_mul(group, r->Y, t0, t1, ctx))
goto err;
if (group->meth->field_set_to_one != NULL) {
if (!group->meth->field_set_to_one(group, r->Z, ctx))
goto err;
} else {
if (!BN_one(r->Z))
goto err;
}
r->Z_is_one = 1;
ret = 1;
err:
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "crypto/ecx.h"
#include "ecx_backend.h"
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
int include_private)
{
size_t privkeylen = 0, pubkeylen;
const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
unsigned char *pubkey;
if (ecx == NULL)
return 0;
param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
if (include_private)
param_priv_key =
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
/*
* If a private key is present then a public key must also be present.
* Alternatively we've just got a public key.
*/
if (param_pub_key == NULL)
return 0;
if (param_priv_key != NULL
&& !OSSL_PARAM_get_octet_string(param_priv_key,
(void **)&ecx->privkey, ecx->keylen,
&privkeylen))
return 0;
pubkey = ecx->pubkey;
if (!OSSL_PARAM_get_octet_string(param_pub_key,
(void **)&pubkey,
sizeof(ecx->pubkey), &pubkeylen))
return 0;
if (pubkeylen != ecx->keylen
|| (param_priv_key != NULL && privkeylen != ecx->keylen))
return 0;
ecx->haspubkey = 1;
return 1;
}
+20
View File
@@ -0,0 +1,20 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define ISX448(id) ((id) == EVP_PKEY_X448)
#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
: ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
: ED448_KEYLEN))
#define KEYNID2TYPE(id) \
(IS25519(id) ? ECX_KEY_TYPE_X25519 \
: ((id) == EVP_PKEY_X448 ? ECX_KEY_TYPE_X448 \
: ((id) == EVP_PKEY_ED25519 ? ECX_KEY_TYPE_ED25519 \
: ECX_KEY_TYPE_ED448)))
#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
+16 -2
View File
@@ -10,7 +10,7 @@
#include <openssl/err.h>
#include "crypto/ecx.h"
ECX_KEY *ecx_key_new(size_t keylen, int haspubkey)
ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey)
{
ECX_KEY *ret = OPENSSL_zalloc(sizeof(*ret));
@@ -18,7 +18,21 @@ ECX_KEY *ecx_key_new(size_t keylen, int haspubkey)
return NULL;
ret->haspubkey = haspubkey;
ret->keylen = keylen;
switch (type) {
case ECX_KEY_TYPE_X25519:
ret->keylen = X25519_KEYLEN;
break;
case ECX_KEY_TYPE_X448:
ret->keylen = X448_KEYLEN;
break;
case ECX_KEY_TYPE_ED25519:
ret->keylen = ED25519_KEYLEN;
break;
case ECX_KEY_TYPE_ED448:
ret->keylen = ED448_KEYLEN;
break;
}
ret->type = type;
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
+72 -27
View File
@@ -19,20 +19,13 @@
#include <openssl/ec.h>
#include <openssl/rand.h>
#include <openssl/core_names.h>
#include "internal/param_build.h"
#include "openssl/param_build.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/ecx.h"
#include "ec_local.h"
#include "curve448/curve448_local.h"
#define ISX448(id) ((id) == EVP_PKEY_X448)
#define IS25519(id) ((id) == EVP_PKEY_X25519 || (id) == EVP_PKEY_ED25519)
#define KEYLENID(id) (IS25519(id) ? X25519_KEYLEN \
: ((id) == EVP_PKEY_X448 ? X448_KEYLEN \
: ED448_KEYLEN))
#define KEYLEN(p) KEYLENID((p)->ameth->pkey_id)
#include "ecx_backend.h"
typedef enum {
KEY_OP_PUBLIC,
@@ -65,7 +58,7 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const X509_ALGOR *palg,
}
}
key = ecx_key_new(KEYLENID(id), 1);
key = ecx_key_new(KEYNID2TYPE(id), 1);
if (key == NULL) {
ECerr(EC_F_ECX_KEY_OP, ERR_R_MALLOC_FAILURE);
return 0;
@@ -413,38 +406,67 @@ static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
}
static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
EVP_KEYMGMT *to_keymgmt)
EVP_KEYMGMT *to_keymgmt, OPENSSL_CTX *libctx,
const char *propq)
{
const ECX_KEY *key = from->pkey.ecx;
OSSL_PARAM_BLD tmpl;
OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
OSSL_PARAM *params = NULL;
int selection = 0;
int rv = 0;
ossl_param_bld_init(&tmpl);
if (tmpl == NULL)
return 0;
/* A key must at least have a public part */
if (!ossl_param_bld_push_octet_string(&tmpl, OSSL_PKEY_PARAM_PUB_KEY,
if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
key->pubkey, key->keylen))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
if (key->privkey != NULL) {
if (!ossl_param_bld_push_octet_string(&tmpl,
if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
OSSL_PKEY_PARAM_PRIV_KEY,
key->privkey, key->keylen))
goto err;
selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
}
params = ossl_param_bld_to_param(&tmpl);
params = OSSL_PARAM_BLD_to_param(tmpl);
/* We export, the provider imports */
rv = evp_keymgmt_import(to_keymgmt, to_keydata, OSSL_KEYMGMT_SELECT_ALL,
params);
rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
err:
ossl_param_bld_free(params);
OSSL_PARAM_BLD_free(tmpl);
OSSL_PARAM_BLD_free_params(params);
return rv;
}
static int ecx_generic_import_from(const OSSL_PARAM params[], void *key,
int keytype)
{
EVP_PKEY *pkey = key;
ECX_KEY *ecx = ecx_key_new(KEYNID2TYPE(keytype), 0);
if (ecx == NULL) {
ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ecx_key_fromdata(ecx, params, 1)
|| !EVP_PKEY_assign(pkey, keytype, ecx)) {
ecx_key_free(ecx);
return 0;
}
return 1;
}
static int x25519_import_from(const OSSL_PARAM params[], void *key)
{
return ecx_generic_import_from(params, key, EVP_PKEY_X25519);
}
const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
EVP_PKEY_X25519,
EVP_PKEY_X25519,
@@ -487,9 +509,15 @@ const EVP_PKEY_ASN1_METHOD ecx25519_asn1_meth = {
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to
ecx_pkey_export_to,
x25519_import_from
};
static int x448_import_from(const OSSL_PARAM params[], void *key)
{
return ecx_generic_import_from(params, key, EVP_PKEY_X448);
}
const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
EVP_PKEY_X448,
EVP_PKEY_X448,
@@ -532,7 +560,8 @@ const EVP_PKEY_ASN1_METHOD ecx448_asn1_meth = {
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to
ecx_pkey_export_to,
x448_import_from
};
static int ecd_size25519(const EVP_PKEY *pkey)
@@ -607,6 +636,10 @@ static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
return 1;
}
static int ed25519_import_from(const OSSL_PARAM params[], void *key)
{
return ecx_generic_import_from(params, key, EVP_PKEY_ED25519);
}
const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
EVP_PKEY_ED25519,
@@ -648,8 +681,16 @@ const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
ed25519_import_from
};
static int ed448_import_from(const OSSL_PARAM params[], void *key)
{
return ecx_generic_import_from(params, key, EVP_PKEY_ED448);
}
const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
EVP_PKEY_ED448,
EVP_PKEY_ED448,
@@ -690,6 +731,9 @@ const EVP_PKEY_ASN1_METHOD ed448_asn1_meth = {
ecx_set_pub_key,
ecx_get_priv_key,
ecx_get_pub_key,
ecx_pkey_dirty_cnt,
ecx_pkey_export_to,
ed448_import_from
};
static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
@@ -793,7 +837,8 @@ static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
return 0;
}
if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey) == 0)
if (ED25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
NULL) == 0)
return 0;
*siglen = ED25519_SIGSIZE;
return 1;
@@ -834,7 +879,7 @@ static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
if (siglen != ED25519_SIGSIZE)
return 0;
return ED25519_verify(tbs, tbslen, sig, edkey->pubkey);
return ED25519_verify(tbs, tbslen, sig, edkey->pubkey, NULL, NULL);
}
static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
@@ -1100,7 +1145,7 @@ static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
ECX_KEY *key = ecx_key_new(X25519_KEYLEN, 1);
ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
@@ -1142,7 +1187,7 @@ static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
ECX_KEY *key = ecx_key_new(X448_KEYLEN, 1);
ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
unsigned char *privkey = NULL, *pubkey;
if (key == NULL) {
@@ -1187,7 +1232,7 @@ static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
};
unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
ECX_KEY *key = ecx_key_new(ED25519_KEYLEN, 1);
ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
unsigned char *privkey = NULL, *pubkey;
unsigned int sz;
@@ -1244,7 +1289,7 @@ static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
};
unsigned char x_dst[57], buff[114];
ECX_KEY *key = ecx_key_new(ED448_KEYLEN, 1);
ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
unsigned char *privkey = NULL, *pubkey;
EVP_MD_CTX *hashctx = NULL;
+2
View File
@@ -282,6 +282,8 @@ ENGINE *ENGINE_by_id(const char *id)
ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
ENGINE_load_builtin_engines();
if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE);
return NULL;
+2 -2
View File
@@ -68,7 +68,7 @@ void ERR_add_error_txt(const char *separator, const char *txt)
if (separator == NULL)
separator = "";
if (err == 0)
put_error(ERR_LIB_CMP, NULL, 0, "", 0);
put_error(ERR_LIB_NONE, NULL, 0, "", 0);
do {
size_t available_len, data_len;
@@ -125,7 +125,7 @@ void ERR_add_error_txt(const char *separator, const char *txt)
ERR_add_error_data(2, separator, tmp);
OPENSSL_free(tmp);
}
put_error(ERR_LIB_CMP, func, err, file, line);
put_error(ERR_GET_LIB(err), func, err, file, line);
txt = curr;
} else {
if (trailing_separator) {
+52 -8
View File
@@ -291,6 +291,7 @@ CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0
CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify
CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt
CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT:188:
CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\
@@ -1310,6 +1311,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
ossl_statem_server_post_process_message
SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:
SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
@@ -1769,6 +1771,7 @@ X509V3_F_DO_DIRNAME:144:do_dirname
X509V3_F_DO_EXT_I2D:135:do_ext_i2d
X509V3_F_DO_EXT_NCONF:151:do_ext_nconf
X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname
X509V3_F_I2R_ISSUER_SIGN_TOOL:176:
X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED
X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING
X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER
@@ -1808,6 +1811,7 @@ X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex
X509V3_F_V2I_IDP:157:v2i_idp
X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks
X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt
X509V3_F_V2I_ISSUER_SIGN_TOOL:175:
X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS
X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS
X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS
@@ -2075,17 +2079,28 @@ BN_R_P_IS_NOT_PRIME:112:p is not prime
BN_R_TOO_MANY_ITERATIONS:113:too many iterations
BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep
CMP_R_BAD_REQUEST_ID:108:bad request id
CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched
CMP_R_CERTID_NOT_FOUND:109:certid not found
CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted
CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found
CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found
CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match
CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range
CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE:166:checking pbm no secret available
CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning
CMP_R_ENCOUNTERED_WAITING:162:encountered waiting
CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection
CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf
CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep
CMP_R_ERROR_CREATING_CR:163:error creating cr
CMP_R_ERROR_CREATING_ERROR:118:error creating error
CMP_R_ERROR_CREATING_GENM:119:error creating genm
CMP_R_ERROR_CREATING_GENP:120:error creating genp
CMP_R_ERROR_CREATING_IR:164:error creating ir
CMP_R_ERROR_CREATING_KUR:165:error creating kur
CMP_R_ERROR_CREATING_P10CR:121:error creating p10cr
CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf
CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep
@@ -2093,8 +2108,10 @@ CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq
CMP_R_ERROR_CREATING_RP:125:error creating rp
CMP_R_ERROR_CREATING_RR:126:error creating rr
CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message
CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
@@ -2107,29 +2124,41 @@ CMP_R_MISSING_PRIVATE_KEY:131:missing private key
CMP_R_MISSING_PROTECTION:143:missing protection
CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
CMP_R_MISSING_TRUST_STORE:144:missing trust store
CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported
CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported
CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
CMP_R_NO_STDIO:194:no stdio
CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
CMP_R_NULL_ARGUMENT:103:null argument
CMP_R_PKIBODY_ERROR:146:pkibody error
CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
CMP_R_POLLING_FAILED:172:polling failed
CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
CMP_R_RECEIVED_ERROR:180:received error
CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server
CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
sender generalname type not supported
CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
CMP_R_TOTAL_TIMEOUT:184:total timeout
CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
unsupported protection alg dhbasedmac
CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp
CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count
CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_ATTRIBUTE_ERROR:161:attribute error
CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
@@ -2256,6 +2285,11 @@ CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
CRMF_R_MALFORMED_IV:101:malformed iv
CRMF_R_NULL_ARGUMENT:109:null argument
CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key
CRMF_R_POPO_MISSING:121:popo missing
CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key
CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject
CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted
CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm
@@ -2264,7 +2298,6 @@ CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher
CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\
unsupported method for creating popo
CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method
CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted
CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name
CRYPTO_R_CONFLICTING_NAMES:118:conflicting names
CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported
@@ -2489,10 +2522,13 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
EVP_R_FETCH_FAILED:202:fetch failed
EVP_R_FINAL_ERROR:188:final error
EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
EVP_R_INACCESSIBLE_KEY:203:inaccessible key
EVP_R_INITIALIZATION_ERROR:134:initialization error
EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length
@@ -2505,6 +2541,7 @@ EVP_R_INVALID_OPERATION:148:invalid operation
EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
EVP_R_KEYGEN_FAILURE:120:keygen failure
EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
@@ -2515,6 +2552,7 @@ EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
EVP_R_NO_DIGEST_SET:139:no digest set
EVP_R_NO_IMPORT_FUNCTION:206:no import function
EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available
EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
EVP_R_NO_KEY_SET:154:no key set
@@ -2534,6 +2572,7 @@ EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
EVP_R_TOO_MANY_RECORDS:183:too many records
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type
EVP_R_UNKNOWN_OPTION:169:unknown option
EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm
EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm
@@ -2563,12 +2602,13 @@ HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded
HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding
HTTP_R_MISSING_CONTENT_TYPE:121:missing content type
HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location
HTTP_R_RECEIVED_ERROR:105:received error
HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version
HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
HTTP_R_SERVER_RESPONSE_PARSE_ERROR:104:server response parse error
HTTP_R_SERVER_SENT_ERROR:105:server sent error
HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION:106:server sent wrong http version
HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error
HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported
HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported
HTTP_R_TLS_NOT_ENABLED:107:tls not enabled
HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections
@@ -2773,11 +2813,13 @@ PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
PROV_R_FAILED_TO_SIGN:175:failed to sign
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
illegal or unsupported padding mode
PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length
PROV_R_INVALID_AAD:108:invalid aad
PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
PROV_R_INVALID_CURVE:176:invalid curve
PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
PROV_R_INVALID_DATA:115:invalid data
PROV_R_INVALID_DIGEST:122:invalid digest
@@ -2817,6 +2859,7 @@ PROV_R_MISSING_XCGHASH:135:missing xcghash
PROV_R_NOT_SUPPORTED:136:not supported
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
PROV_R_NO_KEY_SET:114:no key set
PROV_R_NO_PARAMETERS_SET:177:no parameters set
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
PROV_R_READ_KEY:159:read key
@@ -2970,6 +3013,7 @@ SM2_R_INVALID_ENCODING:104:invalid encoding
SM2_R_INVALID_FIELD:105:invalid field
SM2_R_NO_PARAMETERS_SET:109:no parameters set
SM2_R_USER_ID_TOO_LARGE:106:user id too large
SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
application data after close notify
SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake
@@ -3126,8 +3170,8 @@ SSL_R_MISSING_TMP_DH_KEY:171:missing tmp dh key
SSL_R_MISSING_TMP_ECDH_KEY:311:missing tmp ecdh key
SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA:293:\
mixed handshake and non handshake data
SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS:295:mixed special operator with groups
SSL_R_NESTED_GROUP:296:nested group
SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS:296:mixed special operator with groups
SSL_R_NESTED_GROUP:297:nested group
SSL_R_NOT_ON_RECORD_BOUNDARY:182:not on record boundary
SSL_R_NOT_REPLACING_CERTIFICATE:289:not replacing certificate
SSL_R_NOT_SERVER:284:not server
@@ -3235,9 +3279,9 @@ SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES:243:unable to load ssl3 sha1 routines
SSL_R_UNEXPECTED_CCS_MESSAGE:262:unexpected ccs message
SSL_R_UNEXPECTED_END_OF_EARLY_DATA:178:unexpected end of early data
SSL_R_UNEXPECTED_EOF_WHILE_READING:294:unexpected eof while reading
SSL_R_UNEXPECTED_GROUP_CLOSE:297:unexpected group close
SSL_R_UNEXPECTED_GROUP_CLOSE:299:unexpected group close
SSL_R_UNEXPECTED_MESSAGE:244:unexpected message
SSL_R_UNEXPECTED_OPERATOR_IN_GROUP:299:unexpected operator in group
SSL_R_UNEXPECTED_OPERATOR_IN_GROUP:305:unexpected operator in group
SSL_R_UNEXPECTED_RECORD:245:unexpected record
SSL_R_UNINITIALIZED:276:uninitialized
SSL_R_UNKNOWN_ALERT_TYPE:246:unknown alert type
+48 -4
View File
@@ -291,6 +291,7 @@ CMS_F_CMS_RECEIPTREQUEST_CREATE0:159:CMS_ReceiptRequest_create0
CMS_F_CMS_RECEIPT_VERIFY:160:cms_Receipt_verify
CMS_F_CMS_RECIPIENTINFO_DECRYPT:134:CMS_RecipientInfo_decrypt
CMS_F_CMS_RECIPIENTINFO_ENCRYPT:169:CMS_RecipientInfo_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_DECRYPT:188:
CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT:178:cms_RecipientInfo_kari_encrypt
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG:175:CMS_RecipientInfo_kari_get0_alg
CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID:173:\
@@ -1310,6 +1311,7 @@ SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE:431:*
SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE:601:\
ossl_statem_server_post_process_message
SSL_F_OSSL_STATEM_SERVER_POST_WORK:602:ossl_statem_server_post_work
SSL_F_OSSL_STATEM_SERVER_PRE_WORK:640:
SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE:603:ossl_statem_server_process_message
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION:418:ossl_statem_server_read_transition
SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION:604:\
@@ -1769,6 +1771,7 @@ X509V3_F_DO_DIRNAME:144:do_dirname
X509V3_F_DO_EXT_I2D:135:do_ext_i2d
X509V3_F_DO_EXT_NCONF:151:do_ext_nconf
X509V3_F_GNAMES_FROM_SECTNAME:156:gnames_from_sectname
X509V3_F_I2R_ISSUER_SIGN_TOOL:176:
X509V3_F_I2S_ASN1_ENUMERATED:121:i2s_ASN1_ENUMERATED
X509V3_F_I2S_ASN1_IA5STRING:149:i2s_ASN1_IA5STRING
X509V3_F_I2S_ASN1_INTEGER:120:i2s_ASN1_INTEGER
@@ -1808,6 +1811,7 @@ X509V3_F_V2I_GENERAL_NAME_EX:117:v2i_GENERAL_NAME_ex
X509V3_F_V2I_IDP:157:v2i_idp
X509V3_F_V2I_IPADDRBLOCKS:159:v2i_IPAddrBlocks
X509V3_F_V2I_ISSUER_ALT:153:v2i_issuer_alt
X509V3_F_V2I_ISSUER_SIGN_TOOL:175:
X509V3_F_V2I_NAME_CONSTRAINTS:147:v2i_NAME_CONSTRAINTS
X509V3_F_V2I_POLICY_CONSTRAINTS:146:v2i_POLICY_CONSTRAINTS
X509V3_F_V2I_POLICY_MAPPINGS:145:v2i_POLICY_MAPPINGS
@@ -2075,17 +2079,28 @@ BN_R_P_IS_NOT_PRIME:112:p is not prime
BN_R_TOO_MANY_ITERATIONS:113:too many iterations
BN_R_TOO_MANY_TEMPORARY_VARIABLES:109:too many temporary variables
CMP_R_ALGORITHM_NOT_SUPPORTED:139:algorithm not supported
CMP_R_BAD_CHECKAFTER_IN_POLLREP:167:bad checkafter in pollrep
CMP_R_BAD_REQUEST_ID:108:bad request id
CMP_R_CERTHASH_UNMATCHED:156:certhash unmatched
CMP_R_CERTID_NOT_FOUND:109:certid not found
CMP_R_CERTIFICATE_NOT_ACCEPTED:169:certificate not accepted
CMP_R_CERTIFICATE_NOT_FOUND:112:certificate not found
CMP_R_CERTREQMSG_NOT_FOUND:157:certreqmsg not found
CMP_R_CERTRESPONSE_NOT_FOUND:113:certresponse not found
CMP_R_CERT_AND_KEY_DO_NOT_MATCH:114:cert and key do not match
CMP_R_CHECKAFTER_OUT_OF_RANGE:181:checkafter out of range
CMP_R_CHECKING_PBM_NO_SECRET_AVAILABLE:166:checking pbm no secret available
CMP_R_ENCOUNTERED_KEYUPDATEWARNING:176:encountered keyupdatewarning
CMP_R_ENCOUNTERED_WAITING:162:encountered waiting
CMP_R_ERROR_CALCULATING_PROTECTION:115:error calculating protection
CMP_R_ERROR_CREATING_CERTCONF:116:error creating certconf
CMP_R_ERROR_CREATING_CERTREP:117:error creating certrep
CMP_R_ERROR_CREATING_CR:163:error creating cr
CMP_R_ERROR_CREATING_ERROR:118:error creating error
CMP_R_ERROR_CREATING_GENM:119:error creating genm
CMP_R_ERROR_CREATING_GENP:120:error creating genp
CMP_R_ERROR_CREATING_IR:164:error creating ir
CMP_R_ERROR_CREATING_KUR:165:error creating kur
CMP_R_ERROR_CREATING_P10CR:121:error creating p10cr
CMP_R_ERROR_CREATING_PKICONF:122:error creating pkiconf
CMP_R_ERROR_CREATING_POLLREP:123:error creating pollrep
@@ -2093,8 +2108,10 @@ CMP_R_ERROR_CREATING_POLLREQ:124:error creating pollreq
CMP_R_ERROR_CREATING_RP:125:error creating rp
CMP_R_ERROR_CREATING_RR:126:error creating rr
CMP_R_ERROR_PARSING_PKISTATUS:107:error parsing pkistatus
CMP_R_ERROR_PROCESSING_MESSAGE:158:error processing message
CMP_R_ERROR_PROTECTING_MESSAGE:127:error protecting message
CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash
CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf
CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection
CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey
CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random
@@ -2107,29 +2124,41 @@ CMP_R_MISSING_PRIVATE_KEY:131:missing private key
CMP_R_MISSING_PROTECTION:143:missing protection
CMP_R_MISSING_SENDER_IDENTIFICATION:111:missing sender identification
CMP_R_MISSING_TRUST_STORE:144:missing trust store
CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED:161:multiple requests not supported
CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED:170:multiple responses not supported
CMP_R_MULTIPLE_SAN_SOURCES:102:multiple san sources
CMP_R_NO_STDIO:194:no stdio
CMP_R_NO_SUITABLE_SENDER_CERT:145:no suitable sender cert
CMP_R_NULL_ARGUMENT:103:null argument
CMP_R_PKIBODY_ERROR:146:pkibody error
CMP_R_PKISTATUSINFO_NOT_FOUND:132:pkistatusinfo not found
CMP_R_POLLING_FAILED:172:polling failed
CMP_R_POTENTIALLY_INVALID_CERTIFICATE:147:potentially invalid certificate
CMP_R_RECEIVED_ERROR:180:received error
CMP_R_RECIPNONCE_UNMATCHED:148:recipnonce unmatched
CMP_R_REQUEST_NOT_ACCEPTED:149:request not accepted
CMP_R_REQUEST_REJECTED_BY_SERVER:182:request rejected by server
CMP_R_SENDER_GENERALNAME_TYPE_NOT_SUPPORTED:150:\
sender generalname type not supported
CMP_R_SRVCERT_DOES_NOT_VALIDATE_MSG:151:srvcert does not validate msg
CMP_R_TOTAL_TIMEOUT:184:total timeout
CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched
CMP_R_TRANSFER_ERROR:159:transfer error
CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody
CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus
CMP_R_UNEXPECTED_PVNO:153:unexpected pvno
CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id
CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type
CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus
CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm
CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type
CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\
unsupported protection alg dhbasedmac
CMP_R_WRONG_ALGORITHM_OID:138:wrong algorithm oid
CMP_R_WRONG_CERTID_IN_RP:187:wrong certid in rp
CMP_R_WRONG_PBM_VALUE:155:wrong pbm value
CMP_R_WRONG_RP_COMPONENT_COUNT:188:wrong rp component count
CMP_R_WRONG_SERIAL_IN_RP:173:wrong serial in rp
CMS_R_ADD_SIGNER_ERROR:99:add signer error
CMS_R_ATTRIBUTE_ERROR:161:attribute error
CMS_R_CERTIFICATE_ALREADY_PRESENT:175:certificate already present
@@ -2256,6 +2285,11 @@ CRMF_R_FAILURE_OBTAINING_RANDOM:107:failure obtaining random
CRMF_R_ITERATIONCOUNT_BELOW_100:108:iterationcount below 100
CRMF_R_MALFORMED_IV:101:malformed iv
CRMF_R_NULL_ARGUMENT:109:null argument
CRMF_R_POPO_INCONSISTENT_PUBLIC_KEY:117:popo inconsistent public key
CRMF_R_POPO_MISSING:121:popo missing
CRMF_R_POPO_MISSING_PUBLIC_KEY:118:popo missing public key
CRMF_R_POPO_MISSING_SUBJECT:119:popo missing subject
CRMF_R_POPO_RAVERIFIED_NOT_ACCEPTED:120:popo raverified not accepted
CRMF_R_SETTING_MAC_ALGOR_FAILURE:110:setting mac algor failure
CRMF_R_SETTING_OWF_ALGOR_FAILURE:111:setting owf algor failure
CRMF_R_UNSUPPORTED_ALGORITHM:112:unsupported algorithm
@@ -2264,7 +2298,6 @@ CRMF_R_UNSUPPORTED_CIPHER:114:unsupported cipher
CRMF_R_UNSUPPORTED_METHOD_FOR_CREATING_POPO:115:\
unsupported method for creating popo
CRMF_R_UNSUPPORTED_POPO_METHOD:116:unsupported popo method
CRMF_R_UNSUPPORTED_POPO_NOT_ACCEPTED:117:unsupported popo not accepted
CRYPTO_R_BAD_ALGORITHM_NAME:117:bad algorithm name
CRYPTO_R_CONFLICTING_NAMES:118:conflicting names
CRYPTO_R_FIPS_MODE_NOT_SUPPORTED:101:fips mode not supported
@@ -2489,10 +2522,13 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
EVP_R_FETCH_FAILED:202:fetch failed
EVP_R_FINAL_ERROR:188:final error
EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS:204:inaccessible domain parameters
EVP_R_INACCESSIBLE_KEY:203:inaccessible key
EVP_R_INITIALIZATION_ERROR:134:initialization error
EVP_R_INPUT_NOT_INITIALIZED:111:input not initialized
EVP_R_INVALID_CUSTOM_LENGTH:185:invalid custom length
@@ -2505,6 +2541,7 @@ EVP_R_INVALID_OPERATION:148:invalid operation
EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
EVP_R_KEYGEN_FAILURE:120:keygen failure
EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
EVP_R_KEY_SETUP_FAILED:180:key setup failed
EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
@@ -2515,6 +2552,7 @@ EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
EVP_R_NO_CIPHER_SET:131:no cipher set
EVP_R_NO_DEFAULT_DIGEST:158:no default digest
EVP_R_NO_DIGEST_SET:139:no digest set
EVP_R_NO_IMPORT_FUNCTION:206:no import function
EVP_R_NO_KEYMGMT_AVAILABLE:199:no keymgmt available
EVP_R_NO_KEYMGMT_PRESENT:196:no keymgmt present
EVP_R_NO_KEY_SET:154:no key set
@@ -2534,6 +2572,7 @@ EVP_R_PUBLIC_KEY_NOT_RSA:106:public key not rsa
EVP_R_TOO_MANY_RECORDS:183:too many records
EVP_R_UNKNOWN_CIPHER:160:unknown cipher
EVP_R_UNKNOWN_DIGEST:161:unknown digest
EVP_R_UNKNOWN_KEY_TYPE:207:unknown key type
EVP_R_UNKNOWN_OPTION:169:unknown option
EVP_R_UNKNOWN_PBE_ALGORITHM:121:unknown pbe algorithm
EVP_R_UNSUPPORTED_ALGORITHM:156:unsupported algorithm
@@ -2563,12 +2602,13 @@ HTTP_R_MAX_RESP_LEN_EXCEEDED:117:max resp len exceeded
HTTP_R_MISSING_ASN1_ENCODING:110:missing asn1 encoding
HTTP_R_MISSING_CONTENT_TYPE:121:missing content type
HTTP_R_MISSING_REDIRECT_LOCATION:111:missing redirect location
HTTP_R_RECEIVED_ERROR:105:received error
HTTP_R_RECEIVED_WRONG_HTTP_VERSION:106:received wrong http version
HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP:112:redirection from https to http
HTTP_R_REDIRECTION_NOT_ENABLED:116:redirection not enabled
HTTP_R_RESPONSE_LINE_TOO_LONG:113:response line too long
HTTP_R_SERVER_RESPONSE_PARSE_ERROR:104:server response parse error
HTTP_R_SERVER_SENT_ERROR:105:server sent error
HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION:106:server sent wrong http version
HTTP_R_RESPONSE_PARSE_ERROR:104:response parse error
HTTP_R_SOCK_NOT_SUPPORTED:122:sock not supported
HTTP_R_STATUS_CODE_UNSUPPORTED:114:status code unsupported
HTTP_R_TLS_NOT_ENABLED:107:tls not enabled
HTTP_R_TOO_MANY_REDIRECTIONS:115:too many redirections
@@ -2773,11 +2813,13 @@ PROV_R_FAILED_TO_DECRYPT:162:failed to decrypt
PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key
PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
PROV_R_FAILED_TO_SIGN:175:failed to sign
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\
illegal or unsupported padding mode
PROV_R_INAVLID_UKM_LENGTH:146:inavlid ukm length
PROV_R_INVALID_AAD:108:invalid aad
PROV_R_INVALID_CONSTANT_LENGTH:157:invalid constant length
PROV_R_INVALID_CURVE:176:invalid curve
PROV_R_INVALID_CUSTOM_LENGTH:111:invalid custom length
PROV_R_INVALID_DATA:115:invalid data
PROV_R_INVALID_DIGEST:122:invalid digest
@@ -2817,6 +2859,7 @@ PROV_R_MISSING_XCGHASH:135:missing xcghash
PROV_R_NOT_SUPPORTED:136:not supported
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
PROV_R_NO_KEY_SET:114:no key set
PROV_R_NO_PARAMETERS_SET:177:no parameters set
PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
PROV_R_PSS_SALTLEN_TOO_SMALL:172:pss saltlen too small
PROV_R_READ_KEY:159:read key
@@ -3076,6 +3119,7 @@ SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received
SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request
+3 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -59,7 +59,8 @@ static ESS_CERT_ID *ESS_CERT_ID_new_init(X509 *cert, int issuer_needed)
X509_check_purpose(cert, -1, 0);
if ((cid = ESS_CERT_ID_new()) == NULL)
goto err;
X509_digest(cert, EVP_sha1(), cert_sha1, NULL);
if (!X509_digest(cert, EVP_sha1(), cert_sha1, NULL))
goto err;
if (!ASN1_OCTET_STRING_set(cid->hash, cert_sha1, SHA_DIGEST_LENGTH))
goto err;
+3 -3
View File
@@ -657,12 +657,12 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
size_t sz;
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
if (ctx == NULL || ctx->digest == NULL) {
ERR_raise(ERR_LIB_EVP, EVP_R_MESSAGE_DIGEST_IS_NULL);
if (ctx == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ctx->digest->prov == NULL)
if (ctx->digest != NULL && ctx->digest->prov == NULL)
goto legacy;
switch (cmd) {
+9 -1
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -64,12 +64,16 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
"expecting a poly1305 key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY),
"expecting a siphash key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FETCH_FAILED), "fetch failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
"fips mode not supported"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_ILLEGAL_SCRYPT_PARAMETERS),
"illegal scrypt parameters"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS),
"inaccessible domain parameters"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INACCESSIBLE_KEY), "inaccessible key"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INITIALIZATION_ERROR),
"initialization error"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INPUT_NOT_INITIALIZED),
@@ -87,6 +91,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH),
"invalid salt length"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE),
"keymgmt export failure"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEY_SETUP_FAILED), "key setup failed"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MEMORY_LIMIT_EXCEEDED),
"memory limit exceeded"},
@@ -102,6 +108,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DEFAULT_DIGEST), "no default digest"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_DIGEST_SET), "no digest set"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_IMPORT_FUNCTION), "no import function"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_AVAILABLE),
"no keymgmt available"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_KEYMGMT_PRESENT), "no keymgmt present"},
@@ -128,6 +135,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_TOO_MANY_RECORDS), "too many records"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_CIPHER), "unknown cipher"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_DIGEST), "unknown digest"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_KEY_TYPE), "unknown key type"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_OPTION), "unknown option"},
{ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNKNOWN_PBE_ALGORITHM),
"unknown pbe algorithm"},
+48 -6
View File
@@ -294,9 +294,26 @@ void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
return inner_evp_generic_fetch(libctx,
operation_id, 0, name, properties,
new_method, up_ref_method, free_method);
void *ret = inner_evp_generic_fetch(libctx,
operation_id, 0, name, properties,
new_method, up_ref_method, free_method);
if (ret == NULL) {
int code = EVP_R_FETCH_FAILED;
#ifdef FIPS_MODE
ERR_raise(ERR_LIB_EVP, code);
#else
ERR_raise_data(ERR_LIB_EVP, code,
"%s, Algorithm (%s), Properties (%s)",
(openssl_ctx_is_default(libctx)
? "Default library context"
: "Non-default library context"),
name = NULL ? "<null>" : name,
properties == NULL ? "<null>" : properties);
#endif
}
return ret;
}
/*
@@ -314,9 +331,34 @@ void *evp_generic_fetch_by_number(OPENSSL_CTX *libctx, int operation_id,
int (*up_ref_method)(void *),
void (*free_method)(void *))
{
return inner_evp_generic_fetch(libctx,
operation_id, name_id, NULL, properties,
new_method, up_ref_method, free_method);
void *ret = inner_evp_generic_fetch(libctx,
operation_id, name_id, NULL,
properties, new_method, up_ref_method,
free_method);
if (ret == NULL) {
int code = EVP_R_FETCH_FAILED;
#ifdef FIPS_MODE
ERR_raise(ERR_LIB_EVP, code);
#else
{
OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
const char *name = (namemap == NULL)
? NULL
: ossl_namemap_num2name(namemap, name_id, 0);
ERR_raise_data(ERR_LIB_EVP, code,
"%s, Algorithm (%s), Properties (%s)",
(openssl_ctx_is_default(libctx)
? "Default library context"
: "Non-default library context"),
name = NULL ? "<null>" : name,
properties == NULL ? "<null>" : properties);
}
#endif
}
return ret;
}
int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq)
+12
View File
@@ -81,6 +81,16 @@ struct evp_keymgmt_st {
OSSL_OP_keymgmt_set_params_fn *set_params;
OSSL_OP_keymgmt_settable_params_fn *settable_params;
/* Generation, a complex constructor */
OSSL_OP_keymgmt_gen_init_fn *gen_init;
OSSL_OP_keymgmt_gen_set_template_fn *gen_set_template;
OSSL_OP_keymgmt_gen_set_params_fn *gen_set_params;
OSSL_OP_keymgmt_gen_settable_params_fn *gen_settable_params;
OSSL_OP_keymgmt_gen_get_params_fn *gen_get_params;
OSSL_OP_keymgmt_gen_gettable_params_fn *gen_gettable_params;
OSSL_OP_keymgmt_gen_fn *gen;
OSSL_OP_keymgmt_gen_cleanup_fn *gen_cleanup;
/* Key object checking */
OSSL_OP_keymgmt_query_operation_name_fn *query_operation_name;
OSSL_OP_keymgmt_has_fn *has;
@@ -129,9 +139,11 @@ struct evp_signature_st {
OSSL_OP_signature_digest_sign_init_fn *digest_sign_init;
OSSL_OP_signature_digest_sign_update_fn *digest_sign_update;
OSSL_OP_signature_digest_sign_final_fn *digest_sign_final;
OSSL_OP_signature_digest_sign_fn *digest_sign;
OSSL_OP_signature_digest_verify_init_fn *digest_verify_init;
OSSL_OP_signature_digest_verify_update_fn *digest_verify_update;
OSSL_OP_signature_digest_verify_final_fn *digest_verify_final;
OSSL_OP_signature_digest_verify_fn *digest_verify;
OSSL_OP_signature_freectx_fn *freectx;
OSSL_OP_signature_dupctx_fn *dupctx;
OSSL_OP_signature_get_ctx_params_fn *get_ctx_params;
+1 -1
View File
@@ -197,7 +197,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
*/
ERR_set_mark();
if (ctx->engine != NULL || ctx->keytype == NULL)
if (ctx->keymgmt == NULL)
goto legacy;
/*
+105 -43
View File
@@ -39,13 +39,26 @@ static int try_import(const OSSL_PARAM params[], void *arg)
{
struct import_data_st *data = arg;
/*
* It's fine if there was no data to transfer, we just end up with an
* empty destination key.
*/
if (params[0].key == NULL)
return 1;
/* Just in time creation of keydata, if needed */
if (data->keydata == NULL
&& (data->keydata = evp_keymgmt_newdata(data->keymgmt)) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
}
return evp_keymgmt_import(data->keymgmt, data->keydata, data->selection,
params);
}
void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
{
void *keydata = NULL;
struct import_data_st import_data;
size_t i = 0;
@@ -54,7 +67,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
return NULL;
/* If we have an unassigned key, give up */
if (pk->keymgmt == NULL)
if (pk->keydata == NULL)
return NULL;
/* If |keymgmt| matches the "origin" |keymgmt|, no more to do */
@@ -91,10 +104,6 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
if (!ossl_assert(match_type(pk->keymgmt, keymgmt)))
return NULL;
/* Create space to import data into */
if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL)
return NULL;
/*
* We look at the already cached provider keys, and import from the
* first that supports it (i.e. use its export function), and export
@@ -102,7 +111,7 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
*/
/* Setup for the export callback */
import_data.keydata = keydata;
import_data.keydata = NULL; /* try_import will create it */
import_data.keymgmt = keymgmt;
import_data.selection = OSSL_KEYMGMT_SELECT_ALL;
@@ -113,17 +122,17 @@ void *evp_keymgmt_util_export_to_provider(EVP_PKEY *pk, EVP_KEYMGMT *keymgmt)
if (!evp_keymgmt_export(pk->keymgmt, pk->keydata, OSSL_KEYMGMT_SELECT_ALL,
&try_import, &import_data)) {
/* If there was an error, bail out */
evp_keymgmt_freedata(keymgmt, keydata);
evp_keymgmt_freedata(keymgmt, import_data.keydata);
return NULL;
}
/* Add the new export to the operation cache */
if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, keydata)) {
evp_keymgmt_freedata(keymgmt, keydata);
if (!evp_keymgmt_util_cache_keydata(pk, i, keymgmt, import_data.keydata)) {
evp_keymgmt_freedata(keymgmt, import_data.keydata);
return NULL;
}
return keydata;
return import_data.keydata;
}
void evp_keymgmt_util_clear_operation_cache(EVP_PKEY *pk)
@@ -175,7 +184,7 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk)
*
* This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
*/
if (pk->keymgmt != NULL) {
if (pk->keydata != NULL) {
int bits = 0;
int security_bits = 0;
int size = 0;
@@ -197,17 +206,15 @@ void evp_keymgmt_util_cache_keyinfo(EVP_PKEY *pk)
void *evp_keymgmt_util_fromdata(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
int selection, const OSSL_PARAM params[])
{
void *keydata = evp_keymgmt_newdata(keymgmt);
void *keydata = NULL;
if ((keydata = evp_keymgmt_newdata(keymgmt)) == NULL
|| !evp_keymgmt_import(keymgmt, keydata, selection, params)
|| !EVP_PKEY_set_type_by_keymgmt(target, keymgmt)) {
evp_keymgmt_freedata(keymgmt, keydata);
keydata = NULL;
}
if (keydata != NULL) {
if (!evp_keymgmt_import(keymgmt, keydata, selection, params)
|| !EVP_KEYMGMT_up_ref(keymgmt)) {
evp_keymgmt_freedata(keymgmt, keydata);
return NULL;
}
evp_keymgmt_util_clear_operation_cache(target);
target->keymgmt = keymgmt;
target->keydata = keydata;
evp_keymgmt_util_cache_keyinfo(target);
}
@@ -254,7 +261,17 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
keydata2 = pk2->keydata;
if (keymgmt1 != keymgmt2) {
void *tmp_keydata = NULL;
/*
* The condition for a successful cross export is that the
* keydata to be exported is NULL (typed, but otherwise empty
* EVP_PKEY), or that it was possible to export it with
* evp_keymgmt_util_export_to_provider().
*
* We use |ok| to determine if it's ok to cross export one way,
* but also to determine if we should attempt a cross export
* the other way. There's no point doing it both ways.
*/
int ok = 1;
/* Complex case, where the keymgmt differ */
if (keymgmt1 != NULL
@@ -270,17 +287,35 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
*/
if (keymgmt2 != NULL
&& keymgmt2->match != NULL) {
tmp_keydata = evp_keymgmt_util_export_to_provider(pk1, keymgmt2);
if (tmp_keydata != NULL) {
void *tmp_keydata = NULL;
ok = 1;
if (keydata1 != NULL) {
tmp_keydata =
evp_keymgmt_util_export_to_provider(pk1, keymgmt2);
ok = (tmp_keydata != NULL);
}
if (ok) {
keymgmt1 = keymgmt2;
keydata1 = tmp_keydata;
}
}
if (tmp_keydata == NULL
/*
* If we've successfully cross exported one way, there's no point
* doing it the other way, hence the |!ok| check.
*/
if (!ok
&& keymgmt1 != NULL
&& keymgmt1->match != NULL) {
tmp_keydata = evp_keymgmt_util_export_to_provider(pk2, keymgmt1);
if (tmp_keydata != NULL) {
void *tmp_keydata = NULL;
ok = 1;
if (keydata2 != NULL) {
tmp_keydata =
evp_keymgmt_util_export_to_provider(pk2, keymgmt1);
ok = (tmp_keydata != NULL);
}
if (ok) {
keymgmt2 = keymgmt1;
keydata2 = tmp_keydata;
}
@@ -291,6 +326,13 @@ int evp_keymgmt_util_match(EVP_PKEY *pk1, EVP_PKEY *pk2, int selection)
if (keymgmt1 != keymgmt2)
return -2;
/* If both keydata are NULL, then they're the same key */
if (keydata1 == NULL && keydata2 == NULL)
return 1;
/* If only one of the keydata is NULL, then they're different keys */
if (keydata1 == NULL || keydata2 == NULL)
return 0;
/* If both keydata are non-NULL, we let the backend decide */
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
}
@@ -301,23 +343,21 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
void *to_keydata = to->keydata, *alloc_keydata = NULL;
/* An unassigned key can't be copied */
if (from == NULL || from->keymgmt == NULL)
if (from == NULL || from->keydata == NULL)
return 0;
/* If |from| doesn't support copying, we fail */
if (from->keymgmt->copy == NULL)
return 0;
/* If |to| doesn't have a provider side "origin" yet, create one */
if (to_keymgmt == NULL) {
to_keydata = alloc_keydata = evp_keymgmt_newdata(from->keymgmt);
if (to_keydata == NULL)
if (to_keymgmt == from->keymgmt && to_keymgmt->copy != NULL) {
/* Make sure there's somewhere to copy to */
if (to_keydata == NULL
&& (to_keydata = evp_keymgmt_newdata(to_keymgmt)) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return 0;
to_keymgmt = from->keymgmt;
}
}
if (to_keymgmt == from->keymgmt) {
/* |to| and |from| have the same keymgmt, just copy and be done */
/*
* |to| and |from| have the same keymgmt, and the copy function is
* implemented, so just copy and be done
*/
if (!evp_keymgmt_copy(to_keymgmt, to_keydata, from->keydata,
selection))
return 0;
@@ -333,20 +373,42 @@ int evp_keymgmt_util_copy(EVP_PKEY *to, EVP_PKEY *from, int selection)
evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
return 0;
}
/*
* In this case to_keydata was previously unallocated, try_import()
* may have created it for us.
*/
to_keydata = import_data.keydata;
} else {
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
return 0;
}
if (to->keymgmt == NULL
&& !EVP_KEYMGMT_up_ref(to_keymgmt)) {
&& !EVP_PKEY_set_type_by_keymgmt(to, to_keymgmt)) {
evp_keymgmt_freedata(to_keymgmt, alloc_keydata);
return 0;
}
evp_keymgmt_util_clear_operation_cache(to);
to->keymgmt = to_keymgmt;
to->keydata = to_keydata;
evp_keymgmt_util_cache_keyinfo(to);
return 1;
}
void *evp_keymgmt_util_gen(EVP_PKEY *target, EVP_KEYMGMT *keymgmt,
void *genctx, OSSL_CALLBACK *cb, void *cbarg)
{
void *keydata = NULL;
if ((keydata = evp_keymgmt_gen(keymgmt, genctx, cb, cbarg)) == NULL
|| !EVP_PKEY_set_type_by_keymgmt(target, keymgmt)) {
evp_keymgmt_freedata(keymgmt, keydata);
keydata = NULL;
}
if (keydata != NULL) {
target->keydata = keydata;
evp_keymgmt_util_cache_keyinfo(target);
}
return keydata;
}
+120 -3
View File
@@ -38,7 +38,9 @@ static void *keymgmt_from_dispatch(int name_id,
OSSL_PROVIDER *prov)
{
EVP_KEYMGMT *keymgmt = NULL;
int setparamfncnt = 0, getparamfncnt = 0, importfncnt = 0, exportfncnt = 0;
int setparamfncnt = 0, getparamfncnt = 0;
int setgenparamfncnt = 0, getgenparamfncnt = 0;
int importfncnt = 0, exportfncnt = 0;
if ((keymgmt = keymgmt_new()) == NULL) {
EVP_KEYMGMT_free(keymgmt);
@@ -52,6 +54,51 @@ static void *keymgmt_from_dispatch(int name_id,
if (keymgmt->new == NULL)
keymgmt->new = OSSL_get_OP_keymgmt_new(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_INIT:
if (keymgmt->gen_init == NULL)
keymgmt->gen_init = OSSL_get_OP_keymgmt_gen_init(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
if (keymgmt->gen_set_template == NULL)
keymgmt->gen_set_template =
OSSL_get_OP_keymgmt_gen_set_template(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
if (keymgmt->gen_set_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_set_params =
OSSL_get_OP_keymgmt_gen_set_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
if (keymgmt->gen_settable_params == NULL) {
setgenparamfncnt++;
keymgmt->gen_settable_params =
OSSL_get_OP_keymgmt_gen_settable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN_GET_PARAMS:
if (keymgmt->gen_get_params == NULL) {
getgenparamfncnt++;
keymgmt->gen_get_params =
OSSL_get_OP_keymgmt_gen_get_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN_GETTABLE_PARAMS:
if (keymgmt->gen_gettable_params == NULL) {
getgenparamfncnt++;
keymgmt->gen_gettable_params =
OSSL_get_OP_keymgmt_gen_gettable_params(fns);
}
break;
case OSSL_FUNC_KEYMGMT_GEN:
if (keymgmt->gen == NULL)
keymgmt->gen = OSSL_get_OP_keymgmt_gen(fns);
break;
case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
if (keymgmt->gen_cleanup == NULL)
keymgmt->gen_cleanup = OSSL_get_OP_keymgmt_gen_cleanup(fns);
break;
case OSSL_FUNC_KEYMGMT_FREE:
if (keymgmt->free == NULL)
keymgmt->free = OSSL_get_OP_keymgmt_free(fns);
@@ -134,12 +181,17 @@ static void *keymgmt_from_dispatch(int name_id,
* export if you can't import or export.
*/
if (keymgmt->free == NULL
|| keymgmt->new == NULL
|| (keymgmt->new == NULL && keymgmt->gen == NULL)
|| keymgmt->has == NULL
|| (getparamfncnt != 0 && getparamfncnt != 2)
|| (setparamfncnt != 0 && setparamfncnt != 2)
|| (setgenparamfncnt != 0 && setgenparamfncnt != 2)
|| (getgenparamfncnt != 0 && getgenparamfncnt != 2)
|| (importfncnt != 0 && importfncnt != 2)
|| (exportfncnt != 0 && exportfncnt != 2)) {
|| (exportfncnt != 0 && exportfncnt != 2)
|| (keymgmt->gen != NULL
&& (keymgmt->gen_init == NULL
|| keymgmt->gen_cleanup == NULL))) {
EVP_KEYMGMT_free(keymgmt);
EVPerr(0, EVP_R_INVALID_PROVIDER_FUNCTIONS);
return NULL;
@@ -249,6 +301,71 @@ void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
keymgmt->free(keydata);
}
void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
if (keymgmt->gen_init == NULL)
return NULL;
return keymgmt->gen_init(provctx, selection);
}
int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
void *template)
{
if (keymgmt->gen_set_template == NULL)
return 0;
return keymgmt->gen_set_template(genctx, template);
}
int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
const OSSL_PARAM params[])
{
if (keymgmt->gen_set_params == NULL)
return 0;
return keymgmt->gen_set_params(genctx, params);
}
const OSSL_PARAM *evp_keymgmt_gen_settable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
if (keymgmt->gen_settable_params == NULL)
return NULL;
return keymgmt->gen_settable_params(provctx);
}
int evp_keymgmt_gen_get_params(const EVP_KEYMGMT *keymgmt, void *genctx,
OSSL_PARAM params[])
{
if (keymgmt->gen_get_params == NULL)
return 0;
return keymgmt->gen_get_params(genctx, params);
}
const OSSL_PARAM *evp_keymgmt_gen_gettable_params(const EVP_KEYMGMT *keymgmt)
{
void *provctx = ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt));
if (keymgmt->gen_gettable_params == NULL)
return NULL;
return keymgmt->gen_gettable_params(provctx);
}
void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
OSSL_CALLBACK *cb, void *cbarg)
{
if (keymgmt->gen == NULL)
return NULL;
return keymgmt->gen(genctx, cb, cbarg);
}
void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
{
if (keymgmt->gen != NULL)
keymgmt->gen_cleanup(genctx);
}
int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
OSSL_PARAM params[])
{
+101 -17
View File
@@ -24,10 +24,22 @@ static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen)
return 0;
}
/*
* If we get the "NULL" md then the name comes back as "UNDEF". We want to use
* NULL for this.
*/
static const char *canon_mdname(const char *mdname)
{
if (mdname != NULL && strcmp(mdname, "UNDEF") == 0)
return NULL;
return mdname;
}
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, const char *mdname,
const char *props, ENGINE *e, EVP_PKEY *pkey,
int ver)
OPENSSL_CTX *libctx, int ver)
{
EVP_PKEY_CTX *locpctx = NULL;
EVP_SIGNATURE *signature = NULL;
@@ -47,8 +59,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
ctx->provctx = NULL;
}
if (ctx->pctx == NULL)
ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
if (ctx->pctx == NULL) {
if (libctx != NULL)
ctx->pctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, props);
else
ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
}
if (ctx->pctx == NULL)
return 0;
@@ -61,7 +77,7 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
*/
ERR_set_mark();
if (locpctx->keytype == NULL)
if (locpctx->engine != NULL || locpctx->keytype == NULL)
goto legacy;
/*
@@ -134,12 +150,12 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
if (type != NULL) {
ctx->reqdigest = type;
if (mdname == NULL)
mdname = EVP_MD_name(type);
mdname = canon_mdname(EVP_MD_name(type));
} else {
if (mdname == NULL
&& EVP_PKEY_get_default_digest_name(locpctx->pkey, locmdname,
sizeof(locmdname)))
mdname = locmdname;
mdname = canon_mdname(locmdname);
if (mdname != NULL) {
/*
@@ -184,6 +200,9 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
*/
ERR_pop_to_mark();
if (type == NULL && mdname != NULL)
type = evp_get_digestbyname_ex(locpctx->libctx, mdname);
if (ctx->pctx->pmeth == NULL) {
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
@@ -238,35 +257,38 @@ static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
* This indicates the current algorithm requires
* special treatment before hashing the tbs-message.
*/
ctx->pctx->flag_call_digest_custom = 0;
if (ctx->pctx->pmeth->digest_custom != NULL)
return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx);
ctx->pctx->flag_call_digest_custom = 1;
return 1;
}
int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname, const char *props, EVP_PKEY *pkey)
const char *mdname, const char *props, EVP_PKEY *pkey,
OPENSSL_CTX *libctx)
{
return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 0);
return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx,
0);
}
int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 0);
return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 0);
}
int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const char *mdname, const char *props,
EVP_PKEY *pkey)
EVP_PKEY *pkey, OPENSSL_CTX *libctx)
{
return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 1);
return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, libctx, 1);
}
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey)
{
return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 1);
return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, NULL, 1);
}
#endif /* FIPS_MDOE */
@@ -280,10 +302,21 @@ int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|| pctx->op.sig.signature == NULL)
goto legacy;
if (pctx->op.sig.signature->digest_sign_update == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.sigprovctx,
data, dsize);
legacy:
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
return EVP_DigestUpdate(ctx, data, dsize);
}
@@ -297,10 +330,21 @@ int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize)
|| pctx->op.sig.signature == NULL)
goto legacy;
if (pctx->op.sig.signature->digest_verify_update == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.sigprovctx,
data, dsize);
legacy:
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
return EVP_DigestUpdate(ctx, data, dsize);
}
@@ -326,6 +370,12 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
return 0;
}
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
if (sigret == NULL)
return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
@@ -391,8 +441,22 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
{
if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL)
return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
EVP_PKEY_CTX *pctx = ctx->pctx;
if (pctx != NULL
&& pctx->operation == EVP_PKEY_OP_SIGNCTX
&& pctx->op.sig.sigprovctx != NULL
&& pctx->op.sig.signature != NULL) {
if (pctx->op.sig.signature->digest_sign != NULL)
return pctx->op.sig.signature->digest_sign(pctx->op.sig.sigprovctx,
sigret, siglen, SIZE_MAX,
tbs, tbslen);
} else {
/* legacy */
if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL)
return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen);
}
if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
return 0;
return EVP_DigestSignFinal(ctx, sigret, siglen);
@@ -422,6 +486,12 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
return 0;
}
/* do_sigver_init() checked that |digest_custom| is non-NULL */
if (pctx->flag_call_digest_custom
&& !ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx))
return 0;
pctx->flag_call_digest_custom = 0;
if (pctx->pmeth->verifyctx != NULL)
vctx = 1;
else
@@ -454,8 +524,22 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs, size_t tbslen)
{
if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL)
return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
EVP_PKEY_CTX *pctx = ctx->pctx;
if (pctx != NULL
&& pctx->operation == EVP_PKEY_OP_VERIFYCTX
&& pctx->op.sig.sigprovctx != NULL
&& pctx->op.sig.signature != NULL) {
if (pctx->op.sig.signature->digest_verify != NULL)
return pctx->op.sig.signature->digest_verify(pctx->op.sig.sigprovctx,
sigret, siglen,
tbs, tbslen);
} else {
/* legacy */
if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL)
return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen);
}
if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
return -1;
return EVP_DigestVerifyFinal(ctx, sigret, siglen);
+666 -203
View File
@@ -24,6 +24,7 @@
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/cmac.h>
#include <openssl/engine.h>
#include <openssl/params.h>
@@ -32,13 +33,24 @@
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "internal/evp.h"
#include "internal/provider.h"
#include "evp_local.h"
#include "crypto/ec.h"
/* TODO remove this when the EVP_PKEY_is_a() #legacy support hack is removed */
#include "e_os.h" /* strcasecmp on Windows */
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len, EVP_KEYMGMT *keymgmt);
static void evp_pkey_free_it(EVP_PKEY *key);
#ifndef FIPS_MODE
/* The type of parameters selected in key parameter functions */
# define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
int EVP_PKEY_bits(const EVP_PKEY *pkey)
{
if (pkey != NULL) {
@@ -84,6 +96,16 @@ int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
return 0;
}
int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg)
{
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
}
void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx)
{
return CRYPTO_get_ex_data(&key->ex_data, idx);
}
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
/*
@@ -92,16 +114,35 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
*/
/*
* Only check that type match this early when both keys are legacy.
* If either of them is provided, we let evp_keymgmt_util_copy()
* do this check, after having exported either of them that isn't
* provided.
* If |to| is a legacy key and |from| isn't, we must downgrade |from|.
* If that fails, this function fails.
*/
if (to->keymgmt == NULL && from->keymgmt == NULL) {
if (to->type == EVP_PKEY_NONE) {
if (to->type != EVP_PKEY_NONE && from->keymgmt != NULL)
if (!evp_pkey_downgrade((EVP_PKEY *)from))
return 0;
/*
* Make sure |to| is typed. Content is less important at this early
* stage.
*
* 1. If |to| is untyped, assign |from|'s key type to it.
* 2. If |to| contains a legacy key, compare its |type| to |from|'s.
* (|from| was already downgraded above)
*
* If |to| is a provided key, there's nothing more to do here, functions
* like evp_keymgmt_util_copy() and evp_pkey_export_to_provider() called
* further down help us find out if they are the same or not.
*/
if (to->type == EVP_PKEY_NONE && to->keymgmt == NULL) {
if (from->type != EVP_PKEY_NONE) {
if (EVP_PKEY_set_type(to, from->type) == 0)
return 0;
} else if (to->type != from->type) {
} else {
if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0)
return 0;
}
} else if (to->type != EVP_PKEY_NONE) {
if (to->type != from->type) {
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
goto err;
}
@@ -119,34 +160,9 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
return 0;
}
/*
* If |from| is provided, we upgrade |to| to be provided as well.
* This drops the legacy key from |to|.
* evp_pkey_upgrade_to_provider() checks if |to| is already provided,
* we don't need to do that here.
*
* TODO(3.0) We should investigate if that's too aggressive and make
* this scenario unsupported instead.
*/
if (from->keymgmt != NULL) {
EVP_KEYMGMT *tmp_keymgmt = from->keymgmt;
/*
* The returned pointer is known to be cached, so we don't have to
* save it. However, if it's NULL, something went wrong and we can't
* copy.
*/
if (evp_pkey_upgrade_to_provider(to, NULL,
&tmp_keymgmt, NULL) == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* For purely provided keys, we just call the keymgmt utility */
if (to->keymgmt != NULL && from->keymgmt != NULL)
return evp_keymgmt_util_copy(to, (EVP_PKEY *)from,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
return evp_keymgmt_util_copy(to, (EVP_PKEY *)from, SELECT_PARAMETERS);
/*
* If |to| is provided, we know that |from| is legacy at this point.
@@ -159,12 +175,16 @@ int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
NULL);
/*
* If we get a NULL, it could be an internal error, or it could be
* that there's a key mismatch. We're pretending the latter...
*/
if (from_keydata == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
return 0;
}
return evp_keymgmt_copy(to->keymgmt, to->keydata, from_keydata,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
SELECT_PARAMETERS);
}
/* Both keys are legacy */
@@ -178,8 +198,7 @@ int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
{
if (pkey != NULL) {
if (pkey->keymgmt != NULL)
return !evp_keymgmt_util_has((EVP_PKEY *)pkey,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS);
else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
return pkey->ameth->param_missing(pkey);
}
@@ -206,20 +225,25 @@ static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
/*
* Here, we know that we have a mixture of legacy and provided keys.
* Try cross export and compare the resulting key data.
* At this point, one of them is provided, the other not. This allows
* us to compare types using legacy NIDs.
*/
if ((a->type != EVP_PKEY_NONE
&& !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type)))
|| (b->type != EVP_PKEY_NONE
&& !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type))))
return -1; /* not the same key type */
/*
* We've determined that they both are the same keytype, so the next
* step is to do a bit of cross export to ensure we have keydata for
* both keys in the same keymgmt.
*/
keymgmt1 = a->keymgmt;
keydata1 = a->keydata;
keymgmt2 = b->keymgmt;
keydata2 = b->keydata;
if ((keymgmt1 == NULL
&& !EVP_KEYMGMT_is_a(keymgmt2, OBJ_nid2sn(a->type)))
|| (keymgmt2 == NULL
&& !EVP_KEYMGMT_is_a(keymgmt1, OBJ_nid2sn(b->type))))
return -1; /* not the same key type */
if (keymgmt2 != NULL && keymgmt2->match != NULL) {
tmp_keydata =
evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
@@ -252,7 +276,7 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
*/
if (a->keymgmt != NULL || b->keymgmt != NULL)
return evp_pkey_cmp_any(a, b, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS);
/* All legacy keys */
if (a->type != b->type)
@@ -270,9 +294,8 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
*/
if (a->keymgmt != NULL || b->keymgmt != NULL)
return evp_pkey_cmp_any(a, b,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
return evp_pkey_cmp_any(a, b, (SELECT_PARAMETERS
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY));
/* All legacy keys */
if (a->type != b->type)
@@ -294,57 +317,6 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
return -2;
}
/*
* Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
* is NULL just return 1 or 0 if the algorithm exists.
*/
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len)
{
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE **eptr = (e == NULL) ? &e : NULL;
if (pkey) {
if (pkey->pkey.ptr)
evp_pkey_free_it(pkey);
/*
* If key type matches and a method exists then this lookup has
* succeeded once so just indicate success.
*/
if ((type == pkey->save_type) && pkey->ameth)
return 1;
# ifndef OPENSSL_NO_ENGINE
/* If we have ENGINEs release them */
ENGINE_finish(pkey->engine);
pkey->engine = NULL;
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = NULL;
# endif
}
if (str)
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
else
ameth = EVP_PKEY_asn1_find(eptr, type);
# ifndef OPENSSL_NO_ENGINE
if (pkey == NULL && eptr != NULL)
ENGINE_finish(e);
# endif
if (ameth == NULL) {
EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
if (pkey) {
pkey->ameth = ameth;
pkey->engine = e;
pkey->type = pkey->ameth->pkey_id;
pkey->save_type = type;
}
return 1;
}
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *priv,
size_t len)
@@ -352,7 +324,7 @@ EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL
|| !pkey_set_type(ret, e, type, NULL, -1)) {
|| !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
/* EVPerr already called */
goto err;
}
@@ -382,7 +354,7 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL
|| !pkey_set_type(ret, e, type, NULL, -1)) {
|| !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
/* EVPerr already called */
goto err;
}
@@ -408,6 +380,7 @@ EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len)
{
/* TODO(3.0) Do we need to do anything about provider side keys? */
if (pkey->ameth->get_priv_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -425,6 +398,7 @@ int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len)
{
/* TODO(3.0) Do we need to do anything about provider side keys? */
if (pkey->ameth->get_pub_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -457,8 +431,8 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t paramsn = 0;
if (ret == NULL
|| cmctx == NULL
|| !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) {
|| cmctx == NULL
|| !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1, NULL)) {
/* EVPerr already called */
goto err;
}
@@ -499,12 +473,12 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
return pkey_set_type(pkey, NULL, type, NULL, -1);
return pkey_set_type(pkey, NULL, type, NULL, -1, NULL);
}
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL);
}
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
@@ -573,6 +547,10 @@ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
return NULL;
}
return pkey->pkey.ptr;
}
@@ -628,6 +606,10 @@ int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
return NULL;
}
if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) {
EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
return NULL;
@@ -655,6 +637,10 @@ int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
return NULL;
}
if (pkey->type != EVP_PKEY_DSA) {
EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
@@ -683,6 +669,10 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
return NULL;
}
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
return NULL;
@@ -713,6 +703,10 @@ int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
{
if (!evp_pkey_downgrade((EVP_PKEY *)pkey)) {
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_KEY);
return NULL;
}
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY);
return NULL;
@@ -755,6 +749,119 @@ int EVP_PKEY_base_id(const EVP_PKEY *pkey)
return EVP_PKEY_type(pkey->type);
}
int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name)
{
#ifndef FIPS_MODE
if (pkey->keymgmt == NULL) {
/*
* These hard coded cases are pure hackery to get around the fact
* that names in crypto/objects/objects.txt are a mess. There is
* no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's
* fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1,
* the NID of which is used for EVP_PKEY_RSA. Strangely enough,
* "DSA" is accurate... but still, better be safe and hard-code
* names that we know.
* TODO Clean this away along with all other #legacy support.
*/
int type;
if (strcasecmp(name, "RSA") == 0)
type = EVP_PKEY_RSA;
#ifndef OPENSSL_NO_EC
else if (strcasecmp(name, "EC") == 0)
type = EVP_PKEY_EC;
#endif
#ifndef OPENSSL_NO_DSA
else if (strcasecmp(name, "DSA") == 0)
type = EVP_PKEY_DSA;
#endif
else
type = EVP_PKEY_type(OBJ_sn2nid(name));
return EVP_PKEY_type(pkey->type) == type;
}
#endif
return EVP_KEYMGMT_is_a(pkey->keymgmt, name);
}
int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
{
if (pkey->keymgmt == NULL) {
switch (EVP_PKEY_base_id(pkey)) {
case EVP_PKEY_RSA:
return 1;
#ifndef OPENSSL_NO_DSA
case EVP_PKEY_DSA:
return 1;
#endif
#ifndef OPENSSL_NO_EC
case EVP_PKEY_ED25519:
case EVP_PKEY_ED448:
return 1;
case EVP_PKEY_EC: /* Including SM2 */
return EC_KEY_can_sign(pkey->pkey.ec);
#endif
default:
break;
}
} else {
const OSSL_PROVIDER *prov = EVP_KEYMGMT_provider(pkey->keymgmt);
OPENSSL_CTX *libctx = ossl_provider_library_context(prov);
const char *supported_sig =
pkey->keymgmt->query_operation_name != NULL
? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE)
: evp_first_name(prov, pkey->keymgmt->name_id);
EVP_SIGNATURE *signature = NULL;
signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL);
if (signature != NULL) {
EVP_SIGNATURE_free(signature);
return 1;
}
}
return 0;
}
#ifndef OPENSSL_NO_EC
/*
* TODO rewrite when we have proper data extraction functions
* Note: an octet pointer would be desirable!
*/
static OSSL_CALLBACK get_ec_curve_name_cb;
static int get_ec_curve_name_cb(const OSSL_PARAM params[], void *arg)
{
const OSSL_PARAM *p = NULL;
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME)) != NULL)
return OSSL_PARAM_get_utf8_string(p, arg, 0);
/* If there is no curve name, this is not an EC key */
return 0;
}
int evp_pkey_get_EC_KEY_curve_nid(const EVP_PKEY *pkey)
{
int ret = NID_undef;
if (pkey->keymgmt == NULL) {
if (EVP_PKEY_base_id(pkey) == EVP_PKEY_EC) {
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
ret = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
}
} else if (EVP_PKEY_is_a(pkey, "EC") || EVP_PKEY_is_a(pkey, "SM2")) {
char *curve_name = NULL;
ret = evp_keymgmt_export(pkey->keymgmt, pkey->keydata,
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
get_ec_curve_name_cb, &curve_name);
if (ret)
ret = ec_curve_name2nid(curve_name);
OPENSSL_free(curve_name);
}
return ret;
}
#endif
static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
{
@@ -993,10 +1100,192 @@ EVP_PKEY *EVP_PKEY_new(void)
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
goto err;
}
#ifndef FIPS_MODE
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) {
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
#endif
return ret;
err:
CRYPTO_THREAD_lock_free(ret->lock);
OPENSSL_free(ret);
return NULL;
}
/*
* Setup a public key management method.
*
* For legacy keys, either |type| or |str| is expected to have the type
* information. In this case, the setup consists of finding an ASN1 method
* and potentially an ENGINE, and setting those fields in |pkey|.
*
* For provider side keys, |keymgmt| is expected to be non-NULL. In this
* case, the setup consists of setting the |keymgmt| field in |pkey|.
*
* If pkey is NULL just return 1 or 0 if the key management method exists.
*/
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len, EVP_KEYMGMT *keymgmt)
{
#ifndef FIPS_MODE
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
ENGINE **eptr = (e == NULL) ? &e : NULL;
#endif
/*
* The setups can't set both legacy and provider side methods.
* It is forbidden
*/
if (!ossl_assert(type == EVP_PKEY_NONE || keymgmt == NULL)
|| !ossl_assert(e == NULL || keymgmt == NULL)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
if (pkey != NULL) {
int free_it = 0;
#ifndef FIPS_MODE
free_it = free_it || pkey->pkey.ptr != NULL;
#endif
free_it = free_it || pkey->keydata != NULL;
if (free_it)
evp_pkey_free_it(pkey);
#ifndef FIPS_MODE
/*
* If key type matches and a method exists then this lookup has
* succeeded once so just indicate success.
*/
if (pkey->type != EVP_PKEY_NONE
&& type == pkey->save_type
&& pkey->ameth != NULL)
return 1;
# ifndef OPENSSL_NO_ENGINE
/* If we have ENGINEs release them */
ENGINE_finish(pkey->engine);
pkey->engine = NULL;
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = NULL;
# endif
#endif
}
#ifndef FIPS_MODE
if (str != NULL)
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
else if (type != EVP_PKEY_NONE)
ameth = EVP_PKEY_asn1_find(eptr, type);
# ifndef OPENSSL_NO_ENGINE
if (pkey == NULL && eptr != NULL)
ENGINE_finish(e);
# endif
#endif
{
int check = 1;
#ifndef FIPS_MODE
check = check && ameth == NULL;
#endif
check = check && keymgmt == NULL;
if (check) {
EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
}
if (pkey != NULL) {
if (keymgmt != NULL && !EVP_KEYMGMT_up_ref(keymgmt)) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
pkey->keymgmt = keymgmt;
pkey->save_type = type;
pkey->type = type;
#ifndef FIPS_MODE
/*
* If the internal "origin" key is provider side, don't save |ameth|.
* The main reason is that |ameth| is one factor to detect that the
* internal "origin" key is a legacy one.
*/
if (keymgmt == NULL)
pkey->ameth = ameth;
pkey->engine = e;
/*
* The EVP_PKEY_ASN1_METHOD |pkey_id| serves different purposes,
* depending on if we're setting this key to contain a legacy or
* a provider side "origin" key. For a legacy key, we assign it
* to the |type| field, but for a provider side key, we assign it
* to the |save_type| field, because |type| is supposed to be set
* to EVP_PKEY_NONE in that case.
*/
if (keymgmt != NULL)
pkey->save_type = ameth->pkey_id;
else if (pkey->ameth != NULL)
pkey->type = ameth->pkey_id;
#endif
}
return 1;
}
#ifndef FIPS_MODE
static void find_ameth(const char *name, void *data)
{
const char **str = data;
/*
* The error messages from pkey_set_type() are uninteresting here,
* and misleading.
*/
ERR_set_mark();
if (pkey_set_type(NULL, NULL, EVP_PKEY_NONE, name, strlen(name),
NULL)) {
if (str[0] == NULL)
str[0] = name;
else if (str[1] == NULL)
str[1] = name;
}
ERR_pop_to_mark();
}
#endif
int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt)
{
#ifndef FIPS_MODE
# define EVP_PKEY_TYPE_STR str[0]
# define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0]))
/*
* Find at most two strings that have an associated EVP_PKEY_ASN1_METHOD
* Ideally, only one should be found. If two (or more) are found, the
* match is ambiguous. This should never happen, but...
*/
const char *str[2] = { NULL, NULL };
EVP_KEYMGMT_names_do_all(keymgmt, find_ameth, &str);
if (str[1] != NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
#else
# define EVP_PKEY_TYPE_STR NULL
# define EVP_PKEY_TYPE_STRLEN -1
#endif
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE,
EVP_PKEY_TYPE_STR, EVP_PKEY_TYPE_STRLEN,
keymgmt);
#undef EVP_PKEY_TYPE_STR
#undef EVP_PKEY_TYPE_STRLEN
}
int EVP_PKEY_up_ref(EVP_PKEY *pkey)
@@ -1012,13 +1301,12 @@ int EVP_PKEY_up_ref(EVP_PKEY *pkey)
}
#ifndef FIPS_MODE
static void evp_pkey_free_legacy(EVP_PKEY *x)
void evp_pkey_free_legacy(EVP_PKEY *x)
{
if (x->ameth != NULL) {
if (x->ameth->pkey_free != NULL)
x->ameth->pkey_free(x);
x->pkey.ptr = NULL;
x->ameth = NULL;
}
# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(x->engine);
@@ -1026,7 +1314,7 @@ static void evp_pkey_free_legacy(EVP_PKEY *x)
ENGINE_finish(x->pmeth_engine);
x->pmeth_engine = NULL;
# endif
x->type = x->save_type = EVP_PKEY_NONE;
x->type = EVP_PKEY_NONE;
}
#endif /* FIPS_MODE */
@@ -1060,6 +1348,9 @@ void EVP_PKEY_free(EVP_PKEY *x)
return;
REF_ASSERT_ISNT(i < 0);
evp_pkey_free_it(x);
#ifndef FIPS_MODE
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data);
#endif
CRYPTO_THREAD_lock_free(x->lock);
#ifndef FIPS_MODE
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
@@ -1069,13 +1360,16 @@ void EVP_PKEY_free(EVP_PKEY *x)
int EVP_PKEY_size(const EVP_PKEY *pkey)
{
int size = 0;
if (pkey != NULL) {
if (pkey->ameth == NULL)
return pkey->cache.size;
else if (pkey->ameth->pkey_size != NULL)
return pkey->ameth->pkey_size(pkey);
size = pkey->cache.size;
#ifndef FIPS_MODE
if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL)
size = pkey->ameth->pkey_size(pkey);
#endif
}
return 0;
return size;
}
void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
@@ -1085,10 +1379,20 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
EVP_KEYMGMT *allocated_keymgmt = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
void *keydata = NULL;
int check;
if (pk == NULL)
return NULL;
/* No key data => nothing to export */
check = 1;
#ifndef FIPS_MODE
check = check && pk->pkey.ptr == NULL;
#endif
check = check && pk->keydata == NULL;
if (check)
return NULL;
#ifndef FIPS_MODE
if (pk->pkey.ptr != NULL) {
/*
@@ -1105,13 +1409,15 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
*keymgmt = NULL;
}
/* If no keymgmt was given or found, get a default keymgmt */
/*
* If no keymgmt was given or found, get a default keymgmt. We do so by
* letting EVP_PKEY_CTX_new_from_pkey() do it for us, then we steal it.
*/
if (tmp_keymgmt == NULL) {
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
if (ctx != NULL && ctx->keytype != NULL)
tmp_keymgmt = allocated_keymgmt =
EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery);
tmp_keymgmt = ctx->keymgmt;
ctx->keymgmt = NULL;
EVP_PKEY_CTX_free(ctx);
}
@@ -1159,7 +1465,7 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
goto end;
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)) {
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt, libctx, propquery)) {
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
goto end;
@@ -1212,98 +1518,255 @@ void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
}
#ifndef FIPS_MODE
/*
* This differs from exporting in that it releases the legacy key and assigns
* the export keymgmt and keydata to the "origin" provider side key instead
* of the operation cache.
*/
void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
EVP_KEYMGMT **keymgmt,
const char *propquery)
int evp_pkey_downgrade(EVP_PKEY *pk)
{
EVP_KEYMGMT *allocated_keymgmt = NULL;
EVP_KEYMGMT *tmp_keymgmt = NULL;
void *keydata = NULL;
EVP_KEYMGMT *keymgmt = pk->keymgmt;
void *keydata = pk->keydata;
int type = pk->save_type;
const char *keytype = NULL;
if (pk == NULL)
return NULL;
/* If this isn't a provider side key, we're done */
if (keymgmt == NULL)
return 1;
/* Get the key type name for error reporting */
if (type != EVP_PKEY_NONE)
keytype = OBJ_nid2sn(type);
else
keytype =
evp_first_name(EVP_KEYMGMT_provider(keymgmt), keymgmt->name_id);
/*
* If this key is already "upgraded", this function shouldn't have been
* called.
* |save_type| was set when any of the EVP_PKEY_set_type functions
* was called. It was set to EVP_PKEY_NONE if the key type wasn't
* recognised to be any of the legacy key types, and the downgrade
* isn't possible.
*/
if (!ossl_assert(pk->keymgmt == NULL))
return NULL;
if (keymgmt != NULL) {
tmp_keymgmt = *keymgmt;
*keymgmt = NULL;
if (type == EVP_PKEY_NONE) {
ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_KEY_TYPE,
"key type = %s, can't downgrade", keytype);
return 0;
}
/* If the key isn't a legacy one, bail out, but with proper values */
if (pk->pkey.ptr == NULL) {
tmp_keymgmt = pk->keymgmt;
keydata = pk->keydata;
} else {
/* If the legacy key doesn't have an export function, give up */
if (pk->ameth->export_to == NULL)
return NULL;
/* If no keymgmt was given, get a default keymgmt */
if (tmp_keymgmt == NULL) {
EVP_PKEY_CTX *ctx =
EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
if (ctx != NULL && ctx->keytype != NULL)
tmp_keymgmt = allocated_keymgmt =
EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery);
EVP_PKEY_CTX_free(ctx);
}
/* If we still don't have a keymgmt, give up */
if (tmp_keymgmt == NULL)
goto end;
/* Make sure that the keymgmt key type matches the legacy NID */
if (!ossl_assert(EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type))))
goto end;
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
goto end;
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)
|| !EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
evp_keymgmt_freedata(tmp_keymgmt, keydata);
keydata = NULL;
goto end;
}
/*
* Clear the operation cache, all the legacy data, as well as the
* dirty counters
*/
evp_pkey_free_legacy(pk);
pk->dirty_cnt_copy = 0;
evp_keymgmt_util_clear_operation_cache(pk);
pk->keymgmt = tmp_keymgmt;
pk->keydata = keydata;
evp_keymgmt_util_cache_keyinfo(pk);
}
end:
/*
* If nothing was upgraded, |tmp_keymgmt| might point at a freed
* EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
* the caller either way in that case.
* To be able to downgrade, we steal the provider side "origin" keymgmt
* and keydata. We've already grabbed the pointers, so all we need to
* do is clear those pointers in |pk| and then call evp_pkey_free_it().
* That way, we can restore |pk| if we need to.
*/
if (keydata == NULL)
tmp_keymgmt = NULL;
pk->keymgmt = NULL;
pk->keydata = NULL;
evp_pkey_free_it(pk);
if (EVP_PKEY_set_type(pk, type)) {
/* If the key is typed but empty, we're done */
if (keydata == NULL) {
/* We're dropping the EVP_KEYMGMT */
EVP_KEYMGMT_free(keymgmt);
return 1;
}
if (keymgmt != NULL)
*keymgmt = tmp_keymgmt;
if (pk->ameth->import_from == NULL) {
ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION,
"key type = %s", keytype);
} else if (evp_keymgmt_export(keymgmt, keydata,
OSSL_KEYMGMT_SELECT_ALL,
pk->ameth->import_from, pk)) {
/*
* Save the provider side data in the operation cache, so they'll
* find it again. evp_pkey_free_it() cleared the cache, so it's
* safe to assume slot zero is free.
* Note that evp_keymgmt_util_cache_keydata() increments keymgmt's
* reference count.
*/
evp_keymgmt_util_cache_keydata(pk, 0, keymgmt, keydata);
EVP_KEYMGMT_free(allocated_keymgmt);
return keydata;
/* Synchronize the dirty count */
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
/* evp_keymgmt_export() increased the refcount... */
EVP_KEYMGMT_free(keymgmt);
return 1;
}
ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE,
"key type = %s", keytype);
}
/*
* Something went wrong. This could for example happen if the keymgmt
* turns out to be an HSM implementation that refuses to let go of some
* of the key data, typically the private bits. In this case, we restore
* the provider side internal "origin" and leave it at that.
*/
if (!ossl_assert(EVP_PKEY_set_type_by_keymgmt(pk, keymgmt))) {
/* This should not be impossible */
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
return 0;
}
/* EVP_PKEY_set_type_by_keymgmt() increased the refcount... */
EVP_KEYMGMT_free(keymgmt);
pk->keydata = keydata;
evp_keymgmt_util_cache_keyinfo(pk);
return 0; /* No downgrade, but at least the key is restored */
}
#endif /* FIPS_MODE */
const OSSL_PARAM *EVP_PKEY_gettable_params(EVP_PKEY *pkey)
{
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL)
return 0;
return evp_keymgmt_gettable_params(pkey->keymgmt);
}
/*
* For the following methods param->return_size is set to a value
* larger than can be returned by the call to evp_keymgmt_get_params().
* If it is still this value then the parameter was ignored - and in this
* case it returns an error..
*/
int EVP_PKEY_get_bn_param(EVP_PKEY *pkey, const char *key_name, BIGNUM **bn)
{
int ret = 0;
OSSL_PARAM params[2];
unsigned char buffer[2048];
/*
* Use -1 as the terminator here instead of sizeof(buffer) + 1 since
* -1 is less likely to be a valid value.
*/
const size_t not_set = (size_t)-1;
unsigned char *buf = NULL;
size_t buf_sz = 0;
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL
|| key_name == NULL
|| bn == NULL)
return 0;
memset(buffer, 0, sizeof(buffer));
params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer));
/* If the return_size is still not_set then we know it was not found */
params[0].return_size = not_set;
params[1] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params)) {
if (params[0].return_size == not_set
|| params[0].return_size == 0)
return 0;
buf_sz = params[0].return_size;
/*
* If it failed because the buffer was too small then allocate the
* required buffer size and retry.
*/
buf = OPENSSL_zalloc(buf_sz);
if (buf == NULL)
return 0;
params[0].data = buf;
params[0].data_size = buf_sz;
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
goto err;
}
/* Fail if the param was not found */
if (params[0].return_size == not_set)
goto err;
ret = OSSL_PARAM_get_BN(params, bn);
err:
OPENSSL_free(buf);
return ret;
}
int EVP_PKEY_get_octet_string_param(EVP_PKEY *pkey, const char *key_name,
unsigned char *buf, size_t max_buf_sz,
size_t *out_sz)
{
OSSL_PARAM params[2];
const size_t not_set = max_buf_sz + 1;
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL
|| key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz);
params[0].return_size = not_set;
params[1] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
return 0;
if (params[0].return_size == not_set)
return 0;
if (out_sz != NULL)
*out_sz = params[0].return_size;
return 1;
}
int EVP_PKEY_get_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
char *str, size_t max_buf_sz,
size_t *out_sz)
{
OSSL_PARAM params[2];
const size_t not_set = max_buf_sz + 1;
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL
|| key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz);
params[0].return_size = not_set;
params[1] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
return 0;
if (params[0].return_size == not_set)
return 0;
if (out_sz != NULL)
*out_sz = params[0].return_size;
return 1;
}
int EVP_PKEY_get_int_param(EVP_PKEY *pkey, const char *key_name, int *out)
{
OSSL_PARAM params[2];
const size_t not_set = sizeof(int) + 1;
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL
|| key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_int(key_name, out);
params[0].return_size = not_set;
params[1] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
return 0;
if (params[0].return_size == not_set)
return 0;
return 1;
}
int EVP_PKEY_get_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t *out)
{
OSSL_PARAM params[2];
const size_t not_set = sizeof(size_t) + 1;
if (pkey == NULL
|| pkey->keymgmt == NULL
|| pkey->keydata == NULL
|| key_name == NULL)
return 0;
params[0] = OSSL_PARAM_construct_size_t(key_name, out);
params[0].return_size = not_set;
params[1] = OSSL_PARAM_construct_end();
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
return 0;
if (params[0].return_size == not_set)
return 0;
return 1;
}
+79 -9
View File
@@ -51,17 +51,31 @@ static int pkey_mac_init(EVP_PKEY_CTX *ctx)
MAC_PKEY_CTX *hctx;
/* We're being smart and using the same base NIDs for PKEY and for MAC */
int nid = ctx->pmeth->pkey_id;
EVP_MAC *mac = EVP_MAC_fetch(NULL, OBJ_nid2sn(nid), NULL);
EVP_MAC *mac;
ERR_set_mark();
mac = EVP_MAC_fetch(ctx->libctx, OBJ_nid2sn(nid), ctx->propquery);
ERR_pop_to_mark();
/*
* mac == NULL may actually be ok in some situations. In an
* EVP_PKEY_new_mac_key() call a temporary EVP_PKEY_CTX is created with
* default libctx. We don't actually need the underlying MAC to be present
* to successfully set the key in that case. The resulting EVP_PKEY could
* then be used in some other libctx where the MAC *is* present
*/
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
hctx->ctx = EVP_MAC_CTX_new(mac);
if (hctx->ctx == NULL) {
OPENSSL_free(hctx);
return 0;
if (mac != NULL) {
hctx->ctx = EVP_MAC_CTX_new(mac);
if (hctx->ctx == NULL) {
OPENSSL_free(hctx);
return 0;
}
}
if (nid == EVP_PKEY_CMAC) {
@@ -83,6 +97,13 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
MAC_PKEY_CTX *sctx, *dctx;
sctx = EVP_PKEY_CTX_get_data(src);
if (sctx->ctx == NULL) {
/* This actually means the fetch failed during the init call */
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
if (sctx->ctx->data == NULL)
return 0;
@@ -142,7 +163,7 @@ static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx);
if (hctx != NULL) {
EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
EVP_MAC *mac = hctx->ctx != NULL ? EVP_MAC_CTX_mac(hctx->ctx) : NULL;
switch (hctx->type) {
case MAC_TYPE_RAW:
@@ -177,8 +198,15 @@ static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
break;
case MAC_TYPE_MAC:
{
EVP_MAC_CTX *cmkey = EVP_MAC_CTX_dup(hctx->ctx);
EVP_MAC_CTX *cmkey;
if (hctx->ctx == NULL) {
/* This actually means the fetch failed during the init call */
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
cmkey = EVP_MAC_CTX_dup(hctx->ctx);
if (cmkey == NULL)
return 0;
if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx)))
@@ -220,6 +248,12 @@ static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
hctx->type == MAC_TYPE_RAW
&& (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
if (hctx->ctx == NULL) {
/* This actually means the fetch failed during the init call */
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
if (set_key) {
if (!EVP_MAC_is_a(EVP_MAC_CTX_mac(hctx->ctx),
OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx)))))
@@ -285,6 +319,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
ciphname, 0);
params[params_n] = OSSL_PARAM_construct_end();
if (hctx->ctx == NULL) {
/*
* This actually means the fetch failed during the init call
*/
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
if (!EVP_MAC_CTX_set_params(hctx->ctx, params)
|| !EVP_MAC_init(hctx->ctx))
return 0;
@@ -306,8 +348,7 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
if (ctx->pkey == NULL)
return 0;
new_mac_ctx = EVP_MAC_CTX_dup((EVP_MAC_CTX *)ctx->pkey
->pkey.ptr);
new_mac_ctx = EVP_MAC_CTX_dup(ctx->pkey->pkey.ptr);
if (new_mac_ctx == NULL)
return 0;
EVP_MAC_CTX_free(hctx->ctx);
@@ -337,6 +378,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
params[0] =
OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &size);
if (hctx->ctx == NULL) {
/*
* This actually means the fetch failed during the init call
*/
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
if (!EVP_MAC_CTX_set_params(hctx->ctx, params))
return 0;
@@ -373,6 +422,14 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
p2, p1);
params[params_n] = OSSL_PARAM_construct_end();
if (hctx->ctx == NULL) {
/*
* This actually means the fetch failed during the init call
*/
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
return EVP_MAC_CTX_set_params(hctx->ctx, params);
}
break;
@@ -385,6 +442,12 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_DIGESTINIT:
switch (hctx->type) {
case MAC_TYPE_RAW:
if (hctx->ctx == NULL) {
/* This actually means the fetch failed during the init call */
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
/* Ensure that we have attached the implementation */
if (!EVP_MAC_init(hctx->ctx))
return 0;
@@ -456,6 +519,13 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
type, value, strlen(value) + 1, NULL))
return 0;
params[1] = OSSL_PARAM_construct_end();
if (hctx->ctx == NULL) {
/* This actually means the fetch failed during the init call */
EVPerr(0, EVP_R_FETCH_FAILED);
return 0;
}
ok = EVP_MAC_CTX_set_params(hctx->ctx, params);
OPENSSL_free(params[0].data);
return ok;
+33 -16
View File
@@ -35,19 +35,24 @@ int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
if (pkey->type == EVP_PKEY_NONE)
goto not_supported;
#ifndef FIPS_MODE
/* legacy */
/* call customized public key check function first */
if (ctx->pmeth->public_check != NULL)
return ctx->pmeth->public_check(pkey);
/* use default public key check function in ameth */
if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) {
EVPerr(EVP_F_EVP_PKEY_PUBLIC_CHECK,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL)
goto not_supported;
return pkey->ameth->pkey_public_check(pkey);
#endif
not_supported:
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
@@ -68,19 +73,24 @@ int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
if (pkey->type == EVP_PKEY_NONE)
goto not_supported;
#ifndef FIPS_MODE
/* legacy */
/* call customized param check function first */
if (ctx->pmeth->param_check != NULL)
return ctx->pmeth->param_check(pkey);
/* legacy */
/* use default param check function in ameth */
if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) {
EVPerr(EVP_F_EVP_PKEY_PARAM_CHECK,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL)
goto not_supported;
return pkey->ameth->pkey_param_check(pkey);
#endif
not_supported:
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
@@ -101,6 +111,7 @@ int EVP_PKEY_private_check(EVP_PKEY_CTX *ctx)
return evp_keymgmt_validate(keymgmt, key,
OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
/* not supported for legacy keys */
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
@@ -121,6 +132,7 @@ int EVP_PKEY_pairwise_check(EVP_PKEY_CTX *ctx)
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_KEYPAIR);
/* not supported for legacy keys */
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
@@ -141,18 +153,23 @@ int EVP_PKEY_check(EVP_PKEY_CTX *ctx)
if (key != NULL && keymgmt != NULL)
return evp_keymgmt_validate(keymgmt, key, OSSL_KEYMGMT_SELECT_ALL);
if (pkey->type == EVP_PKEY_NONE)
goto not_supported;
#ifndef FIPS_MODE
/* legacy */
/* call customized check function first */
if (ctx->pmeth->check != NULL)
return ctx->pmeth->check(pkey);
/* use default check function in ameth */
if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) {
EVPerr(EVP_F_EVP_PKEY_CHECK,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL)
goto not_supported;
return pkey->ameth->pkey_check(pkey);
#endif
not_supported:
EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
+1 -1
View File
@@ -38,7 +38,7 @@ static int evp_pkey_asym_cipher_init(EVP_PKEY_CTX *ctx, int operation)
*/
ERR_set_mark();
if (ctx->keytype == NULL || ctx->engine != NULL)
if (ctx->engine != NULL || ctx->keytype == NULL)
goto legacy;
/*
+238 -76
View File
@@ -9,7 +9,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <openssl/core.h>
#include <openssl/core_names.h>
#include "internal/cryptlib.h"
#include "internal/core.h"
#include <openssl/objects.h>
#include <openssl/evp.h>
#include "crypto/bn.h"
@@ -17,102 +20,262 @@
#include "crypto/evp.h"
#include "evp_local.h"
#ifndef FIPS_MODE
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_EC)
# define TMP_SM2_HACK
#endif
/* TODO(3.0) remove when provider SM2 key generation is implemented */
#ifdef TMP_SM2_HACK
# include <openssl/ec.h>
# include <openssl/serializer.h>
# include "internal/sizes.h"
#endif
static int gen_init(EVP_PKEY_CTX *ctx, int operation)
{
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;
int ret = 0;
if (ctx == NULL)
goto not_supported;
evp_pkey_ctx_free_old_ops(ctx);
ctx->operation = operation;
if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
goto legacy;
/* TODO remove when provider SM2 key generation is implemented */
#ifdef TMP_SM2_HACK
if (ctx->pmeth != NULL && ctx->pmeth->pkey_id == EVP_PKEY_SM2)
goto legacy;
#endif
switch (operation) {
case EVP_PKEY_OP_PARAMGEN:
ctx->op.keymgmt.genctx =
evp_keymgmt_gen_init(ctx->keymgmt,
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
break;
case EVP_PKEY_OP_KEYGEN:
ctx->op.keymgmt.genctx =
evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR);
break;
}
ctx->operation = EVP_PKEY_OP_PARAMGEN;
if (!ctx->pmeth->paramgen_init)
return 1;
ret = ctx->pmeth->paramgen_init(ctx);
if (ctx->op.keymgmt.genctx == NULL)
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
else
ret = 1;
goto end;
legacy:
#ifdef FIPS_MODE
goto not_supported;
#else
if (ctx->pmeth == NULL
|| (operation == EVP_PKEY_OP_PARAMGEN
&& ctx->pmeth->paramgen == NULL)
|| (operation == EVP_PKEY_OP_KEYGEN
&& ctx->pmeth->keygen == NULL))
goto not_supported;
ret = 1;
switch (operation) {
case EVP_PKEY_OP_PARAMGEN:
if (ctx->pmeth->paramgen_init != NULL)
ret = ctx->pmeth->paramgen_init(ctx);
break;
case EVP_PKEY_OP_KEYGEN:
if (ctx->pmeth->keygen_init != NULL)
ret = ctx->pmeth->keygen_init(ctx);
break;
}
#endif
end:
if (ret <= 0)
ctx->operation = EVP_PKEY_OP_UNDEFINED;
return ret;
not_supported:
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ret = -2;
goto end;
}
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
{
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 == NULL)
return -1;
if (*ppkey == NULL)
*ppkey = EVP_PKEY_new();
if (*ppkey == NULL) {
EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE);
return -1;
}
ret = ctx->pmeth->paramgen(ctx, *ppkey);
if (ret <= 0) {
EVP_PKEY_free(*ppkey);
*ppkey = NULL;
}
return ret;
return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
}
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;
return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
}
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
{
int ret;
EVP_PKEY_CTX *ctx = arg;
const OSSL_PARAM *param = NULL;
int p = -1, n = -1;
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 (ctx->pkey_gencb == NULL)
return 1; /* No callback? That's fine */
if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
== NULL
|| !OSSL_PARAM_get_int(param, &p))
return 0;
if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
== NULL
|| !OSSL_PARAM_get_int(param, &n))
return 0;
ctx->keygen_info[0] = p;
ctx->keygen_info[1] = n;
return ctx->pkey_gencb(ctx);
}
int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
{
int ret = 0;
OSSL_CALLBACK cb;
EVP_PKEY *allocated_pkey = NULL;
if (ppkey == NULL)
return -1;
if (*ppkey == NULL)
*ppkey = EVP_PKEY_new();
if (*ppkey == NULL)
return -1;
if (ctx == NULL)
goto not_supported;
ret = ctx->pmeth->keygen(ctx, *ppkey);
if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
goto not_initialized;
if (*ppkey == NULL)
*ppkey = allocated_pkey = EVP_PKEY_new();
if (*ppkey == NULL) {
ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
return -1;
}
if (ctx->op.keymgmt.genctx == NULL)
goto legacy;
ret = 1;
if (ctx->pkey != NULL) {
EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
void *keydata =
evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
&tmp_keymgmt, ctx->propquery);
if (keydata == NULL)
goto not_supported;
ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
ctx->op.keymgmt.genctx, keydata);
}
/*
* the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
* so we so not need to save it, just check it.
*/
ret = ret
&& (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
ossl_callback_to_pkey_gencb, ctx)
!= NULL);
#ifndef FIPS_MODE
/* In case |*ppkey| was originally a legacy key */
if (ret)
evp_pkey_free_legacy(*ppkey);
#endif
/* TODO remove when SM2 key have been cleanly separated from EC keys */
#ifdef TMP_SM2_HACK
/*
* Legacy SM2 keys are implemented as EC_KEY with a twist. The legacy
* key generation detects the SM2 curve and "magically" changes the pkey
* id accordingly.
* Since we don't have SM2 in the provider implementation, we need to
* downgrade the generated provider side key to a legacy one under the
* same conditions.
*
* THIS IS AN UGLY BUT TEMPORARY HACK
*/
{
char curve_name[OSSL_MAX_NAME_SIZE] = "";
if (EVP_PKEY_CTX_get_ec_paramgen_curve_name(ctx, curve_name,
sizeof(curve_name)) < 1
|| strcmp(curve_name, "SM2") != 0)
goto end;
}
if (!evp_pkey_downgrade(*ppkey)
|| !EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2))
ret = 0;
#endif
goto end;
legacy:
#ifdef FIPS_MODE
goto not_supported;
#else
if (ctx->pkey && !evp_pkey_downgrade(ctx->pkey))
goto not_accessible;
switch (ctx->operation) {
case EVP_PKEY_OP_PARAMGEN:
ret = ctx->pmeth->paramgen(ctx, *ppkey);
break;
case EVP_PKEY_OP_KEYGEN:
ret = ctx->pmeth->keygen(ctx, *ppkey);
break;
default:
goto not_supported;
}
#endif
end:
if (ret <= 0) {
EVP_PKEY_free(*ppkey);
*ppkey = NULL;
if (allocated_pkey != NULL)
*ppkey = NULL;
EVP_PKEY_free(allocated_pkey);
}
return ret;
not_supported:
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
ret = -2;
goto end;
not_initialized:
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
ret = -1;
goto end;
#ifndef FIPS_MODE
not_accessible:
ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
ret = -1;
goto end;
#endif
}
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
{
if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return -1;
}
return EVP_PKEY_gen(ctx, ppkey);
}
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
{
if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return -1;
}
return EVP_PKEY_gen(ctx, ppkey);
}
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
@@ -152,6 +315,8 @@ int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
return ctx->keygen_info[idx];
}
#ifndef FIPS_MODE
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
const unsigned char *key, int keylen)
{
@@ -181,13 +346,10 @@ static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
goto not_supported;
evp_pkey_ctx_free_old_ops(ctx);
ctx->operation = operation;
if (ctx->keymgmt == NULL)
ctx->keymgmt = EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype,
ctx->propquery);
if (ctx->keymgmt == NULL)
goto not_supported;
ctx->operation = operation;
return 1;
not_supported:
+98 -24
View File
@@ -1,4 +1,3 @@
/*
* Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
*
@@ -138,12 +137,13 @@ EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags)
static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
EVP_PKEY *pkey, ENGINE *e,
const char *name, const char *propquery,
const char *keytype, const char *propquery,
int id)
{
EVP_PKEY_CTX *ret;
const EVP_PKEY_METHOD *pmeth = NULL;
EVP_KEYMGMT *keymgmt = NULL;
/*
* When using providers, the context is bound to the algo implementation
@@ -156,15 +156,11 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
* If the key doesn't contain anything legacy, then it must be provided,
* so we extract the necessary information and use that.
*/
if (pkey != NULL && pkey->ameth == NULL) {
if (pkey != NULL && pkey->type == EVP_PKEY_NONE) {
/* If we have an engine, something went wrong somewhere... */
if (!ossl_assert(e == NULL))
return NULL;
name = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id);
/*
* TODO: I wonder if the EVP_PKEY should have the name and propquery
* that were used when building it.... /RL
*/
keytype = evp_first_name(pkey->keymgmt->prov, pkey->keymgmt->name_id);
goto common;
}
#ifndef FIPS_MODE
@@ -187,10 +183,10 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
* since that can only happen internally, it's safe to make an
* assertion.
*/
if (!ossl_assert(e == NULL || name == NULL))
if (!ossl_assert(e == NULL || keytype == NULL))
return NULL;
if (e == NULL)
name = OBJ_nid2sn(id);
keytype = OBJ_nid2sn(id);
# ifndef OPENSSL_NO_ENGINE
if (e == NULL && pkey != NULL)
@@ -225,6 +221,17 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
/* END legacy */
#endif /* FIPS_MODE */
common:
/*
* If there's no engine and there's a name, we try fetching a provider
* implementation.
*/
if (e == NULL && keytype != NULL) {
/* This could fail so ignore errors */
ERR_set_mark();
keymgmt = EVP_KEYMGMT_fetch(libctx, keytype, propquery);
ERR_pop_to_mark();
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
@@ -234,8 +241,9 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
return NULL;
}
ret->libctx = libctx;
ret->keytype = name;
ret->propquery = propquery;
ret->keytype = keytype;
ret->keymgmt = keymgmt;
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
@@ -292,6 +300,9 @@ void evp_pkey_ctx_free_old_ops(EVP_PKEY_CTX *ctx)
EVP_ASYM_CIPHER_free(ctx->op.ciph.cipher);
ctx->op.ciph.ciphprovctx = NULL;
ctx->op.ciph.cipher = NULL;
} else if (EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
if (ctx->op.keymgmt.genctx != NULL && ctx->keymgmt != NULL)
evp_keymgmt_gen_cleanup(ctx->keymgmt, ctx->op.keymgmt.genctx);
}
#endif
}
@@ -569,6 +580,12 @@ int EVP_PKEY_CTX_set_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
&& ctx->op.ciph.cipher->set_ctx_params != NULL)
return ctx->op.ciph.cipher->set_ctx_params(ctx->op.ciph.ciphprovctx,
params);
if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->op.keymgmt.genctx != NULL
&& ctx->keymgmt != NULL
&& ctx->keymgmt->gen_set_params != NULL)
return evp_keymgmt_gen_set_params(ctx->keymgmt, ctx->op.keymgmt.genctx,
params);
return 0;
}
@@ -593,6 +610,12 @@ int EVP_PKEY_CTX_get_params(EVP_PKEY_CTX *ctx, OSSL_PARAM *params)
&& ctx->op.ciph.cipher->get_ctx_params != NULL)
return ctx->op.ciph.cipher->get_ctx_params(ctx->op.ciph.ciphprovctx,
params);
if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->op.keymgmt.genctx != NULL
&& ctx->keymgmt != NULL
&& ctx->keymgmt->gen_get_params != NULL)
return evp_keymgmt_gen_get_params(ctx->keymgmt, ctx->op.keymgmt.genctx,
params);
return 0;
}
@@ -629,6 +652,10 @@ const OSSL_PARAM *EVP_PKEY_CTX_settable_params(EVP_PKEY_CTX *ctx)
&& ctx->op.ciph.cipher != NULL
&& ctx->op.ciph.cipher->settable_ctx_params != NULL)
return ctx->op.ciph.cipher->settable_ctx_params();
if (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->keymgmt != NULL
&& ctx->keymgmt->gen_settable_params != NULL)
return evp_keymgmt_gen_settable_params(ctx->keymgmt);
return NULL;
}
@@ -792,6 +819,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
# ifndef OPENSSL_NO_EC
if (keytype == EVP_PKEY_EC) {
switch (cmd) {
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, p1);
case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
if (p1 == -2) {
return EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx);
@@ -822,6 +851,30 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
}
}
# endif
if (keytype == EVP_PKEY_RSA) {
switch (cmd) {
case EVP_PKEY_CTRL_RSA_OAEP_MD:
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_RSA_MGF1_MD:
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, p1);
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
return EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, p2);
case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, p1);
}
}
/*
* keytype == -1 is used when several key types share the same structure,
* or for generic controls that are the same across multiple key types.
*/
if (keytype == -1) {
switch (cmd) {
case EVP_PKEY_CTRL_MD:
@@ -832,18 +885,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
return EVP_PKEY_CTX_set_rsa_padding(ctx, p1);
case EVP_PKEY_CTRL_GET_RSA_PADDING:
return EVP_PKEY_CTX_get_rsa_padding(ctx, p2);
case EVP_PKEY_CTRL_RSA_OAEP_MD:
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_RSA_MGF1_MD:
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
return EVP_PKEY_CTX_get_rsa_oaep_md(ctx, p2);
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
return EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, p2, p1);
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
return EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, (unsigned char **)p2);
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, p1);
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
@@ -854,7 +897,8 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
case EVP_PKEY_CTRL_CMS_DECRYPT:
case EVP_PKEY_CTRL_CMS_ENCRYPT:
# endif
if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
/* TODO (3.0) Temporary hack, this should probe */
if (!EVP_PKEY_is_a(EVP_PKEY_CTX_get0_pkey(ctx), "RSASSA-PSS"))
return 1;
ERR_raise(ERR_LIB_EVP,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
@@ -878,7 +922,9 @@ int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
|| (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.sigprovctx != NULL)
|| (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.ciphprovctx != NULL))
&& ctx->op.ciph.ciphprovctx != NULL)
|| (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->op.keymgmt.genctx != NULL))
return legacy_ctrl_to_param(ctx, keytype, optype, cmd, p1, p2);
if (ctx->pmeth == NULL || ctx->pmeth->ctrl == NULL) {
@@ -920,6 +966,24 @@ int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
const char *value)
{
/* Special cases that we intercept */
# ifndef OPENSSL_NO_EC
/*
* We don't support encoding settings for providers, i.e. the only
* possible encoding is "named_curve", so we simply fail when something
* else is given, and otherwise just pretend all is fine.
*/
if (strcmp(name, "ec_param_enc") == 0) {
if (strcmp(value, "named_curve") == 0) {
return 1;
} else {
ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return -2;
}
}
# endif
if (strcmp(name, "rsa_padding_mode") == 0)
name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE;
else if (strcmp(name, "rsa_mgf1_md") == 0)
@@ -930,11 +994,19 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
name = OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL;
else if (strcmp(name, "rsa_pss_saltlen") == 0)
name = OSSL_SIGNATURE_PARAM_PSS_SALTLEN;
else if (strcmp(name, "rsa_keygen_bits") == 0)
name = OSSL_PKEY_PARAM_RSA_BITS;
else if (strcmp(name, "rsa_keygen_pubexp") == 0)
name = OSSL_PKEY_PARAM_RSA_E;
else if (strcmp(name, "rsa_keygen_primes") == 0)
name = OSSL_PKEY_PARAM_RSA_PRIMES;
# ifndef OPENSSL_NO_DH
else if (strcmp(name, "dh_pad") == 0)
name = OSSL_EXCHANGE_PARAM_PAD;
# endif
# ifndef OPENSSL_NO_EC
else if (strcmp(name, "ec_paramgen_curve") == 0)
name = OSSL_PKEY_PARAM_EC_NAME;
else if (strcmp(name, "ecdh_cofactor_mode") == 0)
name = OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE;
else if (strcmp(name, "ecdh_kdf_md") == 0)
@@ -979,7 +1051,9 @@ int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
|| (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)
&& ctx->op.sig.sigprovctx != NULL)
|| (EVP_PKEY_CTX_IS_ASYM_CIPHER_OP(ctx)
&& ctx->op.ciph.ciphprovctx != NULL))
&& ctx->op.ciph.ciphprovctx != NULL)
|| (EVP_PKEY_CTX_IS_GEN_OP(ctx)
&& ctx->op.keymgmt.genctx != NULL))
return legacy_ctrl_str_to_param(ctx, name, value);
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) {
+27 -7
View File
@@ -105,7 +105,6 @@ static void *evp_signature_from_dispatch(int name_id,
break;
signature->digest_sign_init
= OSSL_get_OP_signature_digest_sign_init(fns);
digsignfncnt++;
break;
case OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE:
if (signature->digest_sign_update != NULL)
@@ -121,12 +120,17 @@ static void *evp_signature_from_dispatch(int name_id,
= OSSL_get_OP_signature_digest_sign_final(fns);
digsignfncnt++;
break;
case OSSL_FUNC_SIGNATURE_DIGEST_SIGN:
if (signature->digest_sign != NULL)
break;
signature->digest_sign
= OSSL_get_OP_signature_digest_sign(fns);
break;
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT:
if (signature->digest_verify_init != NULL)
break;
signature->digest_verify_init
= OSSL_get_OP_signature_digest_verify_init(fns);
digverifyfncnt++;
break;
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE:
if (signature->digest_verify_update != NULL)
@@ -142,6 +146,12 @@ static void *evp_signature_from_dispatch(int name_id,
= OSSL_get_OP_signature_digest_verify_final(fns);
digverifyfncnt++;
break;
case OSSL_FUNC_SIGNATURE_DIGEST_VERIFY:
if (signature->digest_verify != NULL)
break;
signature->digest_verify
= OSSL_get_OP_signature_digest_verify(fns);
break;
case OSSL_FUNC_SIGNATURE_FREECTX:
if (signature->freectx != NULL)
break;
@@ -216,12 +226,20 @@ static void *evp_signature_from_dispatch(int name_id,
&& verifyfncnt == 0
&& verifyrecfncnt == 0
&& digsignfncnt == 0
&& digverifyfncnt == 0)
&& digverifyfncnt == 0
&& signature->digest_sign == NULL
&& signature->digest_verify == NULL)
|| (signfncnt != 0 && signfncnt != 2)
|| (verifyfncnt != 0 && verifyfncnt != 2)
|| (verifyrecfncnt != 0 && verifyrecfncnt != 2)
|| (digsignfncnt != 0 && digsignfncnt != 3)
|| (digverifyfncnt != 0 && digverifyfncnt != 3)
|| (digsignfncnt != 0 && digsignfncnt != 2)
|| (digsignfncnt == 2 && signature->digest_sign_init == NULL)
|| (digverifyfncnt != 0 && digverifyfncnt != 2)
|| (digverifyfncnt == 2 && signature->digest_verify_init == NULL)
|| (signature->digest_sign != NULL
&& signature->digest_sign_init == NULL)
|| (signature->digest_verify != NULL
&& signature->digest_verify_init == NULL)
|| (gparamfncnt != 0 && gparamfncnt != 2)
|| (sparamfncnt != 0 && sparamfncnt != 2)
|| (gmdparamfncnt != 0 && gmdparamfncnt != 2)
@@ -234,7 +252,9 @@ static void *evp_signature_from_dispatch(int name_id,
* (verify_init verify) or
* (verify_recover_init, verify_recover) or
* (digest_sign_init, digest_sign_update, digest_sign_final) or
* (digest_verify_init, digest_verify_update, digest_verify_final).
* (digest_verify_init, digest_verify_update, digest_verify_final) or
* (digest_sign_init, digest_sign) or
* (digest_verify_init, digest_verify).
*
* set_ctx_params and settable_ctx_params are optional, but if one of
* them is present then the other one must also be present. The same
@@ -339,7 +359,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation)
*/
ERR_set_mark();
if (ctx->keytype == NULL)
if (ctx->keymgmt == NULL)
goto legacy;
/*
+26 -23
View File
@@ -24,19 +24,18 @@ int do_ex_data_init(OPENSSL_CTX *ctx)
/*
* Return the EX_CALLBACKS from the |ex_data| array that corresponds to
* a given class. On success, *holds the lock.*
* The |global| parameter is assumed to be non null (checked by the caller).
*/
static EX_CALLBACKS *get_and_lock(OPENSSL_CTX *ctx, int class_index)
static EX_CALLBACKS *get_and_lock(OSSL_EX_DATA_GLOBAL *global, int class_index)
{
EX_CALLBACKS *ip;
OSSL_EX_DATA_GLOBAL *global = NULL;
if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT) {
CRYPTOerr(CRYPTO_F_GET_AND_LOCK, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
global = openssl_ctx_get_ex_data_global(ctx);
if (global == NULL || global->ex_data_lock == NULL) {
if (global->ex_data_lock == NULL) {
/*
* If we get here, someone (who?) cleaned up the lock, so just
* treat it as an error.
@@ -111,9 +110,10 @@ int crypto_free_ex_index_ex(OPENSSL_CTX *ctx, int class_index, int idx)
if (global == NULL)
return 0;
ip = get_and_lock(ctx, class_index);
ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
if (idx < 0 || idx >= sk_EX_CALLBACK_num(ip->meth))
goto err;
a = sk_EX_CALLBACK_value(ip->meth, idx);
@@ -149,7 +149,7 @@ int crypto_get_ex_new_index_ex(OPENSSL_CTX *ctx, int class_index, long argl,
if (global == NULL)
return -1;
ip = get_and_lock(ctx, class_index);
ip = get_and_lock(global, class_index);
if (ip == NULL)
return -1;
@@ -216,13 +216,12 @@ int crypto_new_ex_data_ex(OPENSSL_CTX *ctx, int class_index, void *obj,
if (global == NULL)
return 0;
ip = get_and_lock(ctx, class_index);
ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
ad->ctx = ctx;
ad->sk = NULL;
mx = sk_EX_CALLBACK_num(ip->meth);
if (mx > 0) {
if (mx < (int)OSSL_NELEM(stack))
@@ -269,16 +268,19 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
EX_CALLBACK **storage = NULL;
EX_CALLBACKS *ip;
int toret = 0;
OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(from->ctx);
if (global == NULL)
return 0;
OSSL_EX_DATA_GLOBAL *global;
to->ctx = from->ctx;
if (from->sk == NULL)
/* Nothing to copy over */
return 1;
if ((ip = get_and_lock(from->ctx, class_index)) == NULL)
global = openssl_ctx_get_ex_data_global(from->ctx);
if (global == NULL)
return 0;
ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
mx = sk_EX_CALLBACK_num(ip->meth);
@@ -340,14 +342,15 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
EX_CALLBACK *f;
EX_CALLBACK *stack[10];
EX_CALLBACK **storage = NULL;
OSSL_EX_DATA_GLOBAL *global;
OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx);
if ((ip = get_and_lock(ad->ctx, class_index)) == NULL)
goto err;
global = openssl_ctx_get_ex_data_global(ad->ctx);
if (global == NULL)
goto err;
ip = get_and_lock(global, class_index);
if (ip == NULL)
goto err;
mx = sk_EX_CALLBACK_num(ip->meth);
if (mx > 0) {
if (mx < (int)OSSL_NELEM(stack))
@@ -392,18 +395,18 @@ int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
EX_CALLBACK *f;
EX_CALLBACKS *ip;
void *curval;
OSSL_EX_DATA_GLOBAL *global = openssl_ctx_get_ex_data_global(ad->ctx);
if (global == NULL)
return 0;
OSSL_EX_DATA_GLOBAL *global;
curval = CRYPTO_get_ex_data(ad, idx);
/* Already there, no need to allocate */
if (curval != NULL)
return 1;
ip = get_and_lock(ad->ctx, class_index);
global = openssl_ctx_get_ex_data_global(ad->ctx);
if (global == NULL)
return 0;
ip = get_and_lock(global, class_index);
if (ip == NULL)
return 0;
f = sk_EX_CALLBACK_value(ip->meth, idx);
+1 -1
View File
@@ -1,7 +1,7 @@
LIBS=../../libcrypto
$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c\
ffc_params_validate.c ffc_key_validate.c
ffc_params_validate.c ffc_key_validate.c ffc_backend.c
SOURCE[../../libcrypto]=$COMMON
SOURCE[../../providers/libfips.a]=$COMMON
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_names.h>
#include "internal/ffc.h"
/*
* The intention with the "backend" source file is to offer backend support
* for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
* implementations alike.
*/
int ffc_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
{
const OSSL_PARAM *param_p, *param_q, *param_g;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
if (ffc == NULL)
return 0;
param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
|| (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
|| (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
goto err;
ffc_params_set0_pqg(ffc, p, q, g);
return 1;
err:
BN_free(p);
BN_free(q);
BN_free(g);
return 0;
}
+68 -45
View File
@@ -21,7 +21,7 @@
#include <openssl/buffer.h>
#include <openssl/http.h>
#include "internal/sockets.h"
#include "internal/cryptlib.h"
#include "internal/cryptlib.h" /* for ossl_assert() */
#include "http_local.h"
@@ -157,7 +157,7 @@ int OSSL_HTTP_REQ_CTX_header(OSSL_HTTP_REQ_CTX *rctx, const char *server,
* Section 5.1.2 of RFC 1945 states that the absoluteURI form is only
* allowed when using a proxy
*/
if (BIO_printf(rctx->mem, "http://%s", server) <= 0)
if (BIO_printf(rctx->mem, OSSL_HTTP_PREFIX"%s", server) <= 0)
return 0;
if (port != NULL && BIO_printf(rctx->mem, ":%s", port) <= 0)
return 0;
@@ -330,7 +330,7 @@ static int parse_http_line1(char *line)
for (code = line; *code != '\0' && !ossl_isspace(*code); code++)
continue;
if (*code == '\0') {
HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR);
HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR);
return 0;
}
@@ -339,7 +339,7 @@ static int parse_http_line1(char *line)
code++;
if (*code == '\0') {
HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR);
HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR);
return 0;
}
@@ -348,7 +348,7 @@ static int parse_http_line1(char *line)
continue;
if (*reason == '\0') {
HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR);
HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR);
return 0;
}
@@ -385,7 +385,7 @@ static int parse_http_line1(char *line)
if (retcode < 400)
HTTPerr(0, HTTP_R_STATUS_CODE_UNSUPPORTED);
else
HTTPerr(0, HTTP_R_SERVER_SENT_ERROR);
HTTPerr(0, HTTP_R_RECEIVED_ERROR);
if (*reason == '\0')
ERR_add_error_data(2, "Code=", code);
else
@@ -577,12 +577,14 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
*line_end = '\0';
}
if (value != NULL && line_end != NULL) {
if (rctx->state == OHS_REDIRECT && strcmp(key, "Location") == 0) {
if (rctx->state == OHS_REDIRECT
&& strcasecmp(key, "Location") == 0) {
rctx->redirection_url = value;
return 0;
}
if (rctx->expected_ct != NULL && strcmp(key, "Content-Type") == 0) {
if (strcmp(rctx->expected_ct, value) != 0) {
if (rctx->expected_ct != NULL
&& strcasecmp(key, "Content-Type") == 0) {
if (strcasecmp(rctx->expected_ct, value) != 0) {
HTTPerr(0, HTTP_R_UNEXPECTED_CONTENT_TYPE);
ERR_add_error_data(4, "expected=", rctx->expected_ct,
",actual=", value);
@@ -590,7 +592,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
}
rctx->expected_ct = NULL; /* content-type has been found */
}
if (strcmp(key, "Content-Length") == 0) {
if (strcasecmp(key, "Content-Length") == 0) {
resp_len = strtoul(value, &line_end, 10);
if (line_end == value || *line_end != '\0') {
HTTPerr(0, HTTP_R_ERROR_PARSING_CONTENT_LENGTH);
@@ -603,7 +605,7 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
}
/* Look for blank line: end of headers */
for (p = rctx->iobuf; *p != '\0' ; p++) {
for (p = rctx->iobuf; *p != '\0'; p++) {
if (*p != '\r' && *p != '\n')
break;
}
@@ -690,23 +692,31 @@ int OSSL_HTTP_REQ_CTX_nbio(OSSL_HTTP_REQ_CTX *rctx)
#ifndef OPENSSL_NO_SOCK
/* set up a new connection BIO, to HTTP server or to HTTP(S) proxy if given */
static BIO *HTTP_new_bio(const char *server, const char *server_port,
const char *proxy, const char *proxy_port)
static BIO *HTTP_new_bio(const char *server /* optionally includes ":port" */,
const char *server_port /* explicit server port */,
const char *proxy /* optionally includes ":port" */)
{
const char *host = server;
const char *host = server, *host_end;
char host_name[100];
const char *port = server_port;
BIO *cbio;
if (server == NULL) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
if (!ossl_assert(server != NULL))
return NULL;
}
if (proxy != NULL) {
host = proxy;
port = proxy_port;
port = NULL;
}
cbio = BIO_new_connect(host);
host_end = strchr(host, '/');
if (host_end != NULL && (size_t)(host_end - host) < sizeof(host_name)) {
/* chop trailing string starting with '/' */
strncpy(host_name, host, host_end - host + 1);
host = host_name;
}
cbio = BIO_new_connect(host /* optionally includes ":port" */);
if (cbio == NULL)
goto end;
if (port != NULL)
@@ -724,7 +734,7 @@ static ASN1_VALUE *BIO_mem_d2i(BIO *mem, const ASN1_ITEM *it)
ASN1_VALUE *resp = ASN1_item_d2i(NULL, &p, len, it);
if (resp == NULL)
HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR);
HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR);
return resp;
}
@@ -812,7 +822,7 @@ static int update_timeout(int timeout, time_t start_time)
* After disconnect the modified BIO will be deallocated using BIO_free_all().
*/
BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
int use_ssl, const char *proxy, const char *proxy_port,
int use_ssl, const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
const STACK_OF(CONF_VALUE) *headers,
@@ -837,17 +847,28 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
HTTPerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
return NULL;
}
/* remaining parameters are checked indirectly by the functions called */
if (bio != NULL)
if (bio != NULL) {
cbio = bio;
else
} else {
#ifndef OPENSSL_NO_SOCK
if ((cbio = HTTP_new_bio(server, port, proxy, proxy_port)) == NULL)
if (server == NULL) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (*port == '\0')
port = NULL;
if (port == NULL && strchr(server, ':') == NULL)
port = use_ssl ? OSSL_HTTPS_PORT : OSSL_HTTP_PORT;
proxy = http_adapt_proxy(proxy, no_proxy, server, use_ssl);
if ((cbio = HTTP_new_bio(server, port, proxy)) == NULL)
return NULL;
#else
HTTPerr(0, HTTP_R_SOCK_NOT_SUPPORTED);
return NULL;
#endif
}
/* remaining parameters are checked indirectly by the functions called */
(void)ERR_set_mark(); /* prepare removing any spurious libssl errors */
if (rbio == NULL && BIO_connect_retry(cbio, timeout) <= 0)
@@ -889,15 +910,17 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
if (lib == ERR_LIB_SSL || lib == ERR_LIB_HTTP
|| (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_TIMEOUT)
|| (lib == ERR_LIB_BIO && reason == BIO_R_CONNECT_ERROR)
# ifndef OPENSSL_NO_CMP
#ifndef OPENSSL_NO_CMP
|| (lib == ERR_LIB_CMP
&& reason == CMP_R_POTENTIALLY_INVALID_CERTIFICATE)
# endif
#endif
) {
BIO_snprintf(buf, 200, "server=%s:%s", server, port);
ERR_add_error_data(1, buf);
if (proxy != NULL)
ERR_add_error_data(2, " proxy=", proxy);
if (err == 0) {
BIO_snprintf(buf, 200, "server has disconnected%s",
BIO_snprintf(buf, 200, " peer has disconnected%s",
use_ssl ? " violating the protocol" :
", likely because it requires the use of TLS");
ERR_add_error_data(1, buf);
@@ -934,8 +957,7 @@ BIO *OSSL_HTTP_transfer(const char *server, const char *port, const char *path,
static int redirection_ok(int n_redir, const char *old_url, const char *new_url)
{
static const char https[] = "https:";
int https_len = 6; /* strlen(https) */
size_t https_len = strlen(OSSL_HTTPS_NAME":");
if (n_redir >= HTTP_VERSION_MAX_REDIRECTIONS) {
HTTPerr(0, HTTP_R_TOO_MANY_REDIRECTIONS);
@@ -943,8 +965,8 @@ static int redirection_ok(int n_redir, const char *old_url, const char *new_url)
}
if (*new_url == '/') /* redirection to same server => same protocol */
return 1;
if (strncmp(old_url, https, https_len) == 0 &&
strncmp(new_url, https, https_len) != 0) {
if (strncmp(old_url, OSSL_HTTPS_NAME":", https_len) == 0 &&
strncmp(new_url, OSSL_HTTPS_NAME":", https_len) != 0) {
HTTPerr(0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP);
return 0;
}
@@ -952,7 +974,7 @@ static int redirection_ok(int n_redir, const char *old_url, const char *new_url)
}
/* Get data via HTTP from server at given URL, potentially with redirection */
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port,
BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
const STACK_OF(CONF_VALUE) *headers,
@@ -980,7 +1002,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port,
break;
new_rpath:
resp = OSSL_HTTP_transfer(host, port, path, use_ssl, proxy, proxy_port,
resp = OSSL_HTTP_transfer(host, port, path, use_ssl, proxy, no_proxy,
bio, rbio,
bio_update_fn, arg, headers, NULL, NULL,
maxline, max_resp_len,
@@ -1013,7 +1035,7 @@ BIO *OSSL_HTTP_get(const char *url, const char *proxy, const char *proxy_port,
/* Get ASN.1-encoded data via HTTP from server at given URL */
ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url,
const char *proxy, const char *proxy_port,
const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
const STACK_OF(CONF_VALUE) *headers,
@@ -1028,7 +1050,7 @@ ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url,
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if ((mem = OSSL_HTTP_get(url, proxy, proxy_port, bio, rbio, bio_update_fn,
if ((mem = OSSL_HTTP_get(url, proxy, no_proxy, bio, rbio, bio_update_fn,
arg, headers, maxline, max_resp_len, timeout,
expected_content_type, 1 /* expect_asn1 */))
!= NULL)
@@ -1040,7 +1062,7 @@ ASN1_VALUE *OSSL_HTTP_get_asn1(const char *url,
/* Post ASN.1-encoded request via HTTP to server return ASN.1 response */
ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port,
const char *path, int use_ssl,
const char *proxy, const char *proxy_port,
const char *proxy, const char *no_proxy,
BIO *bio, BIO *rbio,
OSSL_HTTP_bio_cb_t bio_update_fn, void *arg,
const STACK_OF(CONF_VALUE) *headers,
@@ -1061,7 +1083,7 @@ ASN1_VALUE *OSSL_HTTP_post_asn1(const char *server, const char *port,
/* remaining parameters are checked indirectly */
req_mem = HTTP_asn1_item2bio(req_it, req);
res_mem = OSSL_HTTP_transfer(server, port, path, use_ssl, proxy, proxy_port,
res_mem = OSSL_HTTP_transfer(server, port, path, use_ssl, proxy, no_proxy,
bio, rbio,
bio_update_fn, arg, headers, content_type,
req_mem /* may be NULL */, maxline,
@@ -1107,8 +1129,8 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
const char *proxyuser, const char *proxypass,
int timeout, BIO *bio_err, const char *prog)
{
# undef BUF_SIZE
# define BUF_SIZE (8 * 1024)
#undef BUF_SIZE
#define BUF_SIZE (8 * 1024)
char *mbuf = OPENSSL_malloc(BUF_SIZE);
char *mbufp;
int read_len = 0;
@@ -1117,11 +1139,13 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
int rv;
time_t max_time = timeout > 0 ? time(NULL) + timeout : 0;
if (bio == NULL || server == NULL || port == NULL
if (bio == NULL || server == NULL
|| (bio_err != NULL && prog == NULL)) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
goto end;
}
if (port == NULL || *port == '\0')
port = OSSL_HTTPS_PORT;
if (mbuf == NULL || fbio == NULL) {
BIO_printf(bio_err /* may be NULL */, "%s: out of memory", prog);
@@ -1193,7 +1217,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
/* RFC 7231 4.3.6: any 2xx status code is valid */
if (strncmp(mbuf, HTTP_PREFIX, strlen(HTTP_PREFIX)) != 0) {
HTTPerr(0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR);
HTTPerr(0, HTTP_R_RESPONSE_PARSE_ERROR);
BIO_printf(bio_err, "%s: HTTP CONNECT failed, non-HTTP response\n",
prog);
/* Wrong protocol, not even HTTP, so stop reading headers */
@@ -1201,7 +1225,7 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
}
mbufp = mbuf + strlen(HTTP_PREFIX);
if (strncmp(mbufp, HTTP_VERSION_PATT, strlen(HTTP_VERSION_PATT)) != 0) {
HTTPerr(0, HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION);
HTTPerr(0, HTTP_R_RECEIVED_WRONG_HTTP_VERSION);
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, bad HTTP version %.*s\n",
prog, HTTP_VERSION_STR_LEN, mbufp);
@@ -1241,6 +1265,5 @@ int OSSL_HTTP_proxy_connect(BIO *bio, const char *server, const char *port,
}
OPENSSL_free(mbuf);
return ret;
# undef BUF_SIZE
#undef BUF_SIZE
}
+8 -6
View File
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -34,17 +34,19 @@ static const ERR_STRING_DATA HTTP_str_reasons[] = {
"missing content type"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_MISSING_REDIRECT_LOCATION),
"missing redirect location"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_ERROR), "received error"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RECEIVED_WRONG_HTTP_VERSION),
"received wrong http version"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_FROM_HTTPS_TO_HTTP),
"redirection from https to http"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_REDIRECTION_NOT_ENABLED),
"redirection not enabled"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_LINE_TOO_LONG),
"response line too long"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_RESPONSE_PARSE_ERROR),
"server response parse error"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_ERROR), "server sent error"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SERVER_SENT_WRONG_HTTP_VERSION),
"server sent wrong http version"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_RESPONSE_PARSE_ERROR),
"response parse error"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_SOCK_NOT_SUPPORTED),
"sock not supported"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_STATUS_CODE_UNSUPPORTED),
"status code unsupported"},
{ERR_PACK(ERR_LIB_HTTP, 0, HTTP_R_TLS_NOT_ENABLED), "tls not enabled"},
+66 -5
View File
@@ -11,6 +11,9 @@
#include <openssl/httperr.h>
#include <openssl/err.h>
#include <string.h>
#include "internal/cryptlib.h" /* for ossl_assert() */
#include "http_local.h"
/*
* Parse a URL and split it up into host, port and path components and
@@ -22,8 +25,11 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
{
char *p, *buf;
char *host;
char *port = "80";
const char *port = OSSL_HTTP_PORT;
size_t https_len = strlen(OSSL_HTTPS_NAME);
if (!ossl_assert(https_len >= strlen(OSSL_HTTP_NAME)))
return 0;
if (url == NULL) {
HTTPerr(0, ERR_R_PASSED_NULL_PARAMETER);
return 0;
@@ -44,16 +50,16 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
/* Check for initial colon */
p = strchr(buf, ':');
if (p == NULL || p - buf > 5 /* strlen("https") */) {
if (p == NULL || (size_t)(p - buf) > https_len) {
p = buf;
} else {
*(p++) = '\0';
if (strcmp(buf, "https") == 0) {
if (strcmp(buf, OSSL_HTTPS_NAME) == 0) {
if (pssl != NULL)
*pssl = 1;
port = "443";
} else if (strcmp(buf, "http") != 0) {
port = OSSL_HTTPS_PORT;
} else if (strcmp(buf, OSSL_HTTP_NAME) != 0) {
goto parse_err;
}
@@ -114,3 +120,58 @@ int OSSL_HTTP_parse_url(const char *url, char **phost, char **pport,
OPENSSL_free(buf);
return 0;
}
int http_use_proxy(const char *no_proxy, const char *server)
{
size_t sl;
const char *found = NULL;
if (!ossl_assert(server != NULL))
return 0;
sl = strlen(server);
/*
* using environment variable names, both lowercase and uppercase variants,
* compatible with other HTTP client implementations like wget, curl and git
*/
if (no_proxy == NULL)
no_proxy = getenv("no_proxy");
if (no_proxy == NULL)
no_proxy = getenv(OPENSSL_NO_PROXY);
if (no_proxy != NULL)
found = strstr(no_proxy, server);
while (found != NULL
&& ((found != no_proxy && found[-1] != ' ' && found[-1] != ',')
|| (found[sl] != '\0' && found[sl] != ' ' && found[sl] != ',')))
found = strstr(found + 1, server);
return found == NULL;
}
const char *http_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl)
{
const int http_len = strlen(OSSL_HTTP_PREFIX);
const int https_len = strlen(OSSL_HTTPS_PREFIX);
/*
* using environment variable names, both lowercase and uppercase variants,
* compatible with other HTTP client implementations like wget, curl and git
*/
if (proxy == NULL)
proxy = getenv(use_ssl ? "https_proxy" : "http_proxy");
if (proxy == NULL)
proxy = getenv(use_ssl ? OPENSSL_HTTP_PROXY :
OPENSSL_HTTPS_PROXY);
if (proxy == NULL)
return NULL;
/* skip any leading "http://" or "https://" */
if (strncmp(proxy, OSSL_HTTP_PREFIX, http_len) == 0)
proxy += http_len;
else if (strncmp(proxy, OSSL_HTTPS_PREFIX, https_len) == 0)
proxy += https_len;
if (*proxy == '\0' || !http_use_proxy(no_proxy, server))
return NULL;
return proxy;
}
+4 -1
View File
@@ -45,5 +45,8 @@ ASN1_VALUE *HTTP_sendreq_bio(BIO *bio, OSSL_HTTP_bio_cb_t bio_update_fn,
ASN1_VALUE *req, const ASN1_ITEM *req_it,
int maxline, unsigned long max_resp_len,
int timeout, const ASN1_ITEM *rsp_it);
int http_use_proxy(const char *no_proxy, const char *server);
const char *http_adapt_proxy(const char *proxy, const char *no_proxy,
const char *server, int use_ssl);
#endif /* !defined OSSL_CRYPTO_HTTP_LOCAL_H */
#endif /* !defined(OSSL_CRYPTO_HTTP_LOCAL_H) */
+9 -2
View File
@@ -1,3 +1,10 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c
$ALL=i_cbc.c i_cfb64.c i_ofb64.c i_ecb.c i_skey.c
SOURCE[../../libcrypto]=$ALL
# When all deprecated symbols are removed, libcrypto doesn't export the
# idea functions, so we must include them directly in liblegacy.a
IF[{- $disabled{'deprecated-3.0'} -}]
SOURCE[../../providers/liblegacy.a]=$ALL
ENDIF

Some files were not shown because too many files have changed in this diff Show More