Imported Upstream version 4.8.0.309

Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-11-10 13:04:39 +00:00
parent ee1447783b
commit 94b2861243
4912 changed files with 390737 additions and 49310 deletions

View File

@@ -0,0 +1,52 @@
include_directories(../../include)
add_library(
evp
OBJECT
digestsign.c
evp.c
evp_asn1.c
evp_ctx.c
p_dsa_asn1.c
p_ec.c
p_ec_asn1.c
p_rsa.c
p_rsa_asn1.c
pbkdf.c
print.c
sign.c
)
if(ENABLE_TESTS)
add_executable(
evp_extra_test
evp_extra_test.cc
$<TARGET_OBJECTS:test_support>
)
add_executable(
evp_test
evp_test.cc
$<TARGET_OBJECTS:test_support>
)
add_executable(
pbkdf_test
pbkdf_test.cc
$<TARGET_OBJECTS:test_support>
)
target_link_libraries(evp_extra_test crypto)
target_link_libraries(evp_test crypto)
target_link_libraries(pbkdf_test crypto)
add_dependencies(all_tests evp_extra_test evp_test pbkdf_test)
endif()

View File

@@ -0,0 +1,159 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
/* ====================================================================
* Copyright (c) 2006,2007 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal.h"
#include "../digest/internal.h"
static const struct evp_md_pctx_ops md_pctx_ops = {
EVP_PKEY_CTX_free,
EVP_PKEY_CTX_dup,
};
static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
int is_verify) {
if (ctx->pctx == NULL) {
ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
}
if (ctx->pctx == NULL) {
return 0;
}
ctx->pctx_ops = &md_pctx_ops;
if (type == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
return 0;
}
if (is_verify) {
if (!EVP_PKEY_verify_init(ctx->pctx)) {
return 0;
}
} else {
if (!EVP_PKEY_sign_init(ctx->pctx)) {
return 0;
}
}
if (!EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
return 0;
}
if (pctx) {
*pctx = ctx->pctx;
}
if (!EVP_DigestInit_ex(ctx, type, e)) {
return 0;
}
return 1;
}
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, e, pkey, 0);
}
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, e, pkey, 1);
}
int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
return EVP_DigestUpdate(ctx, data, len);
}
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
return EVP_DigestUpdate(ctx, data, len);
}
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
size_t *out_sig_len) {
if (out_sig) {
EVP_MD_CTX tmp_ctx;
int ret;
uint8_t md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
EVP_MD_CTX_init(&tmp_ctx);
ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
EVP_MD_CTX_cleanup(&tmp_ctx);
return ret;
} else {
size_t s = EVP_MD_size(ctx->digest);
return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
}
}
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
size_t sig_len) {
EVP_MD_CTX tmp_ctx;
int ret;
uint8_t md[EVP_MAX_MD_SIZE];
unsigned int mdlen;
EVP_MD_CTX_init(&tmp_ctx);
ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
EVP_MD_CTX_cleanup(&tmp_ctx);
return ret;
}

365
external/boringssl/crypto/evp/evp.c vendored Normal file
View File

@@ -0,0 +1,365 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/evp.h>
#include <assert.h>
#include <string.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
#include <openssl/rsa.h>
#include <openssl/thread.h>
#include "internal.h"
#include "../internal.h"
EVP_PKEY *EVP_PKEY_new(void) {
EVP_PKEY *ret;
ret = OPENSSL_malloc(sizeof(EVP_PKEY));
if (ret == NULL) {
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(ret, 0, sizeof(EVP_PKEY));
ret->type = EVP_PKEY_NONE;
ret->references = 1;
return ret;
}
static void free_it(EVP_PKEY *pkey) {
if (pkey->ameth && pkey->ameth->pkey_free) {
pkey->ameth->pkey_free(pkey);
pkey->pkey.ptr = NULL;
pkey->type = EVP_PKEY_NONE;
}
}
void EVP_PKEY_free(EVP_PKEY *pkey) {
if (pkey == NULL) {
return;
}
if (!CRYPTO_refcount_dec_and_test_zero(&pkey->references)) {
return;
}
free_it(pkey);
OPENSSL_free(pkey);
}
EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey) {
CRYPTO_refcount_inc(&pkey->references);
return pkey;
}
int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
if (pkey->ameth && pkey->ameth->pkey_opaque) {
return pkey->ameth->pkey_opaque(pkey);
}
return 0;
}
int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
return pkey->ameth->pkey_supports_digest(pkey, md);
}
return 1;
}
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
if (a->type != b->type) {
return -1;
}
if (a->ameth) {
int ret;
/* Compare parameters if the algorithm has them */
if (a->ameth->param_cmp) {
ret = a->ameth->param_cmp(a, b);
if (ret <= 0) {
return ret;
}
}
if (a->ameth->pub_cmp) {
return a->ameth->pub_cmp(a, b);
}
}
return -2;
}
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
if (to->type != from->type) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
goto err;
}
if (EVP_PKEY_missing_parameters(from)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
goto err;
}
if (from->ameth && from->ameth->param_copy) {
return from->ameth->param_copy(to, from);
}
err:
return 0;
}
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) {
if (pkey->ameth && pkey->ameth->param_missing) {
return pkey->ameth->param_missing(pkey);
}
return 0;
}
int EVP_PKEY_size(const EVP_PKEY *pkey) {
if (pkey && pkey->ameth && pkey->ameth->pkey_size) {
return pkey->ameth->pkey_size(pkey);
}
return 0;
}
int EVP_PKEY_bits(EVP_PKEY *pkey) {
if (pkey && pkey->ameth && pkey->ameth->pkey_bits) {
return pkey->ameth->pkey_bits(pkey);
}
return 0;
}
int EVP_PKEY_id(const EVP_PKEY *pkey) {
return pkey->type;
}
/* evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which
* should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
* unknown. */
static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
switch (nid) {
case EVP_PKEY_RSA:
return &rsa_asn1_meth;
case EVP_PKEY_EC:
return &ec_asn1_meth;
case EVP_PKEY_DSA:
return &dsa_asn1_meth;
default:
return NULL;
}
}
int EVP_PKEY_type(int nid) {
const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid);
if (meth == NULL) {
return NID_undef;
}
return meth->pkey_id;
}
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) {
if (EVP_PKEY_assign_RSA(pkey, key)) {
RSA_up_ref(key);
return 1;
}
return 0;
}
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_RSA, key);
}
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_RSA_KEY);
return NULL;
}
return pkey->pkey.rsa;
}
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) {
RSA *rsa = EVP_PKEY_get0_RSA(pkey);
if (rsa != NULL) {
RSA_up_ref(rsa);
}
return rsa;
}
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) {
if (EVP_PKEY_assign_DSA(pkey, key)) {
DSA_up_ref(key);
return 1;
}
return 0;
}
int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_DSA, key);
}
DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_DSA) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
}
return pkey->pkey.dsa;
}
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) {
DSA *dsa = EVP_PKEY_get0_DSA(pkey);
if (dsa != NULL) {
DSA_up_ref(dsa);
}
return dsa;
}
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
if (EVP_PKEY_assign_EC_KEY(pkey, key)) {
EC_KEY_up_ref(key);
return 1;
}
return 0;
}
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) {
return EVP_PKEY_assign(pkey, EVP_PKEY_EC, key);
}
EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) {
if (pkey->type != EVP_PKEY_EC) {
OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_AN_EC_KEY_KEY);
return NULL;
}
return pkey->pkey.ec;
}
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) {
EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key != NULL) {
EC_KEY_up_ref(ec_key);
}
return ec_key;
}
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
if (!EVP_PKEY_set_type(pkey, type)) {
return 0;
}
pkey->pkey.ptr = key;
return key != NULL;
}
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
const EVP_PKEY_ASN1_METHOD *ameth;
if (pkey && pkey->pkey.ptr) {
free_it(pkey);
}
ameth = evp_pkey_asn1_find(type);
if (ameth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
ERR_add_error_dataf("algorithm %d", type);
return 0;
}
if (pkey) {
pkey->ameth = ameth;
pkey->type = pkey->ameth->pkey_id;
}
return 1;
}
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
if (a->type != b->type) {
return -1;
}
if (a->ameth && a->ameth->param_cmp) {
return a->ameth->param_cmp(a, b);
}
return -2;
}
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
(void *)md);
}
int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md) {
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_GET_MD,
0, (void *)out_md);
}
void OpenSSL_add_all_algorithms(void) {}
void OPENSSL_add_all_algorithms_conf(void) {}
void OpenSSL_add_all_ciphers(void) {}
void OpenSSL_add_all_digests(void) {}
void EVP_cleanup(void) {}

336
external/boringssl/crypto/evp/evp_asn1.c vendored Normal file
View File

@@ -0,0 +1,336 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/evp.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/dsa.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include "internal.h"
static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
&rsa_asn1_meth,
&ec_asn1_meth,
&dsa_asn1_meth,
};
static int parse_key_type(CBS *cbs, int *out_type) {
CBS oid;
if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
return 0;
}
unsigned i;
for (i = 0; i < sizeof(kASN1Methods)/sizeof(kASN1Methods[0]); i++) {
const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
if (CBS_len(&oid) == method->oid_len &&
memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
*out_type = method->pkey_id;
return 1;
}
}
return 0;
}
EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
/* Parse the SubjectPublicKeyInfo. */
CBS spki, algorithm, key;
int type;
uint8_t padding;
if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
!parse_key_type(&algorithm, &type) ||
!CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
CBS_len(&spki) != 0 ||
/* Every key type defined encodes the key as a byte string with the same
* conversion to BIT STRING. */
!CBS_get_u8(&key, &padding) ||
padding != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return NULL;
}
/* Set up an |EVP_PKEY| of the appropriate type. */
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL ||
!EVP_PKEY_set_type(ret, type)) {
goto err;
}
/* Call into the type-specific SPKI decoding function. */
if (ret->ameth->pub_decode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
goto err;
}
if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
goto err;
}
return ret;
err:
EVP_PKEY_free(ret);
return NULL;
}
int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
return key->ameth->pub_encode(cbb, key);
}
EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
/* Parse the PrivateKeyInfo. */
CBS pkcs8, algorithm, key;
uint64_t version;
int type;
if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBS_get_asn1_uint64(&pkcs8, &version) ||
version != 0 ||
!CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
!parse_key_type(&algorithm, &type) ||
!CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return NULL;
}
/* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */
/* Set up an |EVP_PKEY| of the appropriate type. */
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL ||
!EVP_PKEY_set_type(ret, type)) {
goto err;
}
/* Call into the type-specific PrivateKeyInfo decoding function. */
if (ret->ameth->priv_decode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
goto err;
}
if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
goto err;
}
return ret;
err:
EVP_PKEY_free(ret);
return NULL;
}
int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
return key->ameth->priv_encode(cbb, key);
}
static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL) {
return NULL;
}
switch (type) {
case EVP_PKEY_EC: {
EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
EC_KEY_free(ec_key);
goto err;
}
return ret;
}
case EVP_PKEY_DSA: {
DSA *dsa = DSA_parse_private_key(cbs);
if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
DSA_free(dsa);
goto err;
}
return ret;
}
case EVP_PKEY_RSA: {
RSA *rsa = RSA_parse_private_key(cbs);
if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
RSA_free(rsa);
goto err;
}
return ret;
}
default:
OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
goto err;
}
err:
EVP_PKEY_free(ret);
return NULL;
}
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
long len) {
if (len < 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return NULL;
}
/* Parse with the legacy format. */
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *ret = old_priv_decode(&cbs, type);
if (ret == NULL) {
/* Try again with PKCS#8. */
ERR_clear_error();
CBS_init(&cbs, *inp, (size_t)len);
ret = EVP_parse_private_key(&cbs);
if (ret == NULL) {
return NULL;
}
if (ret->type != type) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
EVP_PKEY_free(ret);
return NULL;
}
}
if (out != NULL) {
EVP_PKEY_free(*out);
*out = ret;
}
*inp = CBS_data(&cbs);
return ret;
}
/* num_elements parses one SEQUENCE from |in| and returns the number of elements
* in it. On parse error, it returns zero. */
static size_t num_elements(const uint8_t *in, size_t in_len) {
CBS cbs, sequence;
CBS_init(&cbs, in, (size_t)in_len);
if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
return 0;
}
size_t count = 0;
while (CBS_len(&sequence) > 0) {
if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
return 0;
}
count++;
}
return count;
}
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
if (len < 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return NULL;
}
/* Parse the input as a PKCS#8 PrivateKeyInfo. */
CBS cbs;
CBS_init(&cbs, *inp, (size_t)len);
EVP_PKEY *ret = EVP_parse_private_key(&cbs);
if (ret != NULL) {
if (out != NULL) {
EVP_PKEY_free(*out);
*out = ret;
}
*inp = CBS_data(&cbs);
return ret;
}
ERR_clear_error();
/* Count the elements to determine the legacy key format. */
switch (num_elements(*inp, (size_t)len)) {
case 4:
return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
case 6:
return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
default:
return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
}
}
int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
switch (key->type) {
case EVP_PKEY_RSA:
return i2d_RSAPublicKey(key->pkey.rsa, outp);
case EVP_PKEY_DSA:
return i2d_DSAPublicKey(key->pkey.dsa, outp);
case EVP_PKEY_EC:
return i2o_ECPublicKey(key->pkey.ec, outp);
default:
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
return -1;
}
}

445
external/boringssl/crypto/evp/evp_ctx.c vendored Normal file
View File

@@ -0,0 +1,445 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/evp.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
static const EVP_PKEY_METHOD *const evp_methods[] = {
&rsa_pkey_meth,
&ec_pkey_meth,
};
static const EVP_PKEY_METHOD *evp_pkey_meth_find(int type) {
unsigned i;
for (i = 0; i < sizeof(evp_methods)/sizeof(EVP_PKEY_METHOD*); i++) {
if (evp_methods[i]->pkey_id == type) {
return evp_methods[i];
}
}
return NULL;
}
static EVP_PKEY_CTX *evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) {
EVP_PKEY_CTX *ret;
const EVP_PKEY_METHOD *pmeth;
if (id == -1) {
if (!pkey || !pkey->ameth) {
return NULL;
}
id = pkey->ameth->pkey_id;
}
pmeth = evp_pkey_meth_find(id);
if (pmeth == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
ERR_add_error_dataf("algorithm %d", id);
return NULL;
}
ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
if (!ret) {
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(ret, 0, sizeof(EVP_PKEY_CTX));
ret->engine = e;
ret->pmeth = pmeth;
ret->operation = EVP_PKEY_OP_UNDEFINED;
if (pkey) {
ret->pkey = EVP_PKEY_up_ref(pkey);
}
if (pmeth->init) {
if (pmeth->init(ret) <= 0) {
EVP_PKEY_free(ret->pkey);
OPENSSL_free(ret);
return NULL;
}
}
return ret;
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) {
return evp_pkey_ctx_new(pkey, e, -1);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) {
return evp_pkey_ctx_new(NULL, e, id);
}
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) {
if (ctx == NULL) {
return;
}
if (ctx->pmeth && ctx->pmeth->cleanup) {
ctx->pmeth->cleanup(ctx);
}
EVP_PKEY_free(ctx->pkey);
EVP_PKEY_free(ctx->peerkey);
OPENSSL_free(ctx);
}
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
EVP_PKEY_CTX *rctx;
if (!pctx->pmeth || !pctx->pmeth->copy) {
return NULL;
}
rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
if (!rctx) {
return NULL;
}
memset(rctx, 0, sizeof(EVP_PKEY_CTX));
rctx->pmeth = pctx->pmeth;
rctx->engine = pctx->engine;
rctx->operation = pctx->operation;
if (pctx->pkey) {
rctx->pkey = EVP_PKEY_up_ref(pctx->pkey);
if (rctx->pkey == NULL) {
goto err;
}
}
if (pctx->peerkey) {
rctx->peerkey = EVP_PKEY_up_ref(pctx->peerkey);
if (rctx->peerkey == NULL) {
goto err;
}
}
if (pctx->pmeth->copy(rctx, pctx) > 0) {
return rctx;
}
err:
EVP_PKEY_CTX_free(rctx);
OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
return NULL;
}
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
int p1, void *p2) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return 0;
}
if (keytype != -1 && ctx->pmeth->pkey_id != keytype) {
return 0;
}
if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_OPERATION_SET);
return 0;
}
if (optype != -1 && !(ctx->operation & optype)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_OPERATION);
return 0;
}
return ctx->pmeth->ctrl(ctx, cmd, p1, p2);
}
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_SIGN;
return 1;
}
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *sig_len,
const uint8_t *data, size_t data_len) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_SIGN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->sign(ctx, sig, sig_len, data, data_len);
}
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_VERIFY;
return 1;
}
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t sig_len,
const uint8_t *data, size_t data_len) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_VERIFY) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->verify(ctx, sig, sig_len, data, data_len);
}
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_ENCRYPT;
return 1;
}
int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen);
}
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_DECRYPT;
return 1;
}
int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
}
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
return 1;
}
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
const uint8_t *sig, size_t sig_len) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->verify_recover(ctx, out, out_len, sig, sig_len);
}
int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_DERIVE;
return 1;
}
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) {
int ret;
if (!ctx || !ctx->pmeth ||
!(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) ||
!ctx->pmeth->ctrl) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_DERIVE &&
ctx->operation != EVP_PKEY_OP_ENCRYPT &&
ctx->operation != EVP_PKEY_OP_DECRYPT) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
if (ret <= 0) {
return 0;
}
if (ret == 2) {
return 1;
}
if (!ctx->pkey) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
return 0;
}
if (ctx->pkey->type != peer->type) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
return 0;
}
/* ran@cryptocom.ru: For clarity. The error is if parameters in peer are
* present (!missing) but don't match. EVP_PKEY_cmp_parameters may return
* 1 (match), 0 (don't match) and -2 (comparison is not defined). -1
* (different key types) is impossible here because it is checked earlier.
* -2 is OK for us here, as well as 1, so we can check for 0 only. */
if (!EVP_PKEY_missing_parameters(peer) &&
!EVP_PKEY_cmp_parameters(ctx->pkey, peer)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_PARAMETERS);
return 0;
}
EVP_PKEY_free(ctx->peerkey);
ctx->peerkey = peer;
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
if (ret <= 0) {
ctx->peerkey = NULL;
return 0;
}
EVP_PKEY_up_ref(peer);
return 1;
}
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *out_key_len) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_DERIVE) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
return ctx->pmeth->derive(ctx, key, out_key_len);
}
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
ctx->operation = EVP_PKEY_OP_KEYGEN;
return 1;
}
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) {
if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
return 0;
}
if (!ppkey) {
return 0;
}
if (!*ppkey) {
*ppkey = EVP_PKEY_new();
if (!*ppkey) {
OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
return 0;
}
}
if (!ctx->pmeth->keygen(ctx, *ppkey)) {
EVP_PKEY_free(*ppkey);
*ppkey = NULL;
return 0;
}
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
/*
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project.
*/
/* ====================================================================
* Copyright (c) 2015 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*/
#include <openssl/evp.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
OPENSSL_MSVC_PRAGMA(warning(push))
OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
#include <map>
#include <string>
#include <utility>
#include <vector>
OPENSSL_MSVC_PRAGMA(warning(pop))
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include "../test/file_test.h"
#include "../test/scoped_types.h"
// evp_test dispatches between multiple test types. PrivateKey tests take a key
// name parameter and single block, decode it as a PEM private key, and save it
// under that key name. Decrypt, Sign, and Verify tests take a previously
// imported key name as parameter and test their respective operations.
static const EVP_MD *GetDigest(FileTest *t, const std::string &name) {
if (name == "MD5") {
return EVP_md5();
} else if (name == "SHA1") {
return EVP_sha1();
} else if (name == "SHA224") {
return EVP_sha224();
} else if (name == "SHA256") {
return EVP_sha256();
} else if (name == "SHA384") {
return EVP_sha384();
} else if (name == "SHA512") {
return EVP_sha512();
}
t->PrintLine("Unknown digest: '%s'", name.c_str());
return nullptr;
}
static int GetKeyType(FileTest *t, const std::string &name) {
if (name == "RSA") {
return EVP_PKEY_RSA;
}
if (name == "EC") {
return EVP_PKEY_EC;
}
if (name == "DSA") {
return EVP_PKEY_DSA;
}
t->PrintLine("Unknown key type: '%s'", name.c_str());
return EVP_PKEY_NONE;
}
using KeyMap = std::map<std::string, ScopedEVP_PKEY>;
static bool ImportKey(FileTest *t, KeyMap *key_map,
EVP_PKEY *(*parse_func)(CBS *cbs),
int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) {
std::vector<uint8_t> input;
if (!t->GetBytes(&input, "Input")) {
return false;
}
CBS cbs;
CBS_init(&cbs, input.data(), input.size());
ScopedEVP_PKEY pkey(parse_func(&cbs));
if (!pkey) {
return false;
}
std::string key_type;
if (!t->GetAttribute(&key_type, "Type")) {
return false;
}
if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) {
t->PrintLine("Bad key type.");
return false;
}
// The key must re-encode correctly.
ScopedCBB cbb;
uint8_t *der;
size_t der_len;
if (!CBB_init(cbb.get(), 0) ||
!marshal_func(cbb.get(), pkey.get()) ||
!CBB_finish(cbb.get(), &der, &der_len)) {
return false;
}
ScopedOpenSSLBytes free_der(der);
std::vector<uint8_t> output = input;
if (t->HasAttribute("Output") &&
!t->GetBytes(&output, "Output")) {
return false;
}
if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) {
t->PrintLine("Re-encoding the key did not match.");
return false;
}
// Save the key for future tests.
const std::string &key_name = t->GetParameter();
if (key_map->count(key_name) > 0) {
t->PrintLine("Duplicate key '%s'.", key_name.c_str());
return false;
}
(*key_map)[key_name] = std::move(pkey);
return true;
}
static bool TestEVP(FileTest *t, void *arg) {
KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
if (t->GetType() == "PrivateKey") {
return ImportKey(t, key_map, EVP_parse_private_key,
EVP_marshal_private_key);
}
if (t->GetType() == "PublicKey") {
return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
}
int (*key_op_init)(EVP_PKEY_CTX *ctx);
int (*key_op)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
const uint8_t *in, size_t in_len);
if (t->GetType() == "Decrypt") {
key_op_init = EVP_PKEY_decrypt_init;
key_op = EVP_PKEY_decrypt;
} else if (t->GetType() == "Sign") {
key_op_init = EVP_PKEY_sign_init;
key_op = EVP_PKEY_sign;
} else if (t->GetType() == "Verify") {
key_op_init = EVP_PKEY_verify_init;
key_op = nullptr; // EVP_PKEY_verify is handled differently.
} else {
t->PrintLine("Unknown test '%s'", t->GetType().c_str());
return false;
}
// Load the key.
const std::string &key_name = t->GetParameter();
if (key_map->count(key_name) == 0) {
t->PrintLine("Could not find key '%s'.", key_name.c_str());
return false;
}
EVP_PKEY *key = (*key_map)[key_name].get();
std::vector<uint8_t> input, output;
if (!t->GetBytes(&input, "Input") ||
!t->GetBytes(&output, "Output")) {
return false;
}
// Set up the EVP_PKEY_CTX.
ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(key, nullptr));
if (!ctx || !key_op_init(ctx.get())) {
return false;
}
if (t->HasAttribute("Digest")) {
const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("Digest"));
if (digest == nullptr ||
!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest)) {
return false;
}
}
if (t->GetType() == "Verify") {
if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
input.size())) {
// ECDSA sometimes doesn't push an error code. Push one on the error queue
// so it's distinguishable from other errors.
OPENSSL_PUT_ERROR(USER, ERR_R_EVP_LIB);
return false;
}
return true;
}
size_t len;
std::vector<uint8_t> actual;
if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
return false;
}
actual.resize(len);
if (!key_op(ctx.get(), actual.data(), &len, input.data(), input.size())) {
return false;
}
actual.resize(len);
if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
return false;
}
return true;
}
int main(int argc, char **argv) {
CRYPTO_library_init();
if (argc != 2) {
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
return 1;
}
KeyMap map;
return FileTestMain(TestEVP, &map, argv[1]);
}

File diff suppressed because one or more lines are too long

237
external/boringssl/crypto/evp/internal.h vendored Normal file
View File

@@ -0,0 +1,237 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#ifndef OPENSSL_HEADER_EVP_INTERNAL_H
#define OPENSSL_HEADER_EVP_INTERNAL_H
#include <openssl/base.h>
#include <openssl/rsa.h>
#if defined(__cplusplus)
extern "C" {
#endif
struct evp_pkey_asn1_method_st {
int pkey_id;
uint8_t oid[9];
uint8_t oid_len;
/* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo
* and writes the result into |out|. It returns one on success and zero on
* error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER
* type field, and |key| is the contents of the subjectPublicKey with the
* leading padding byte checked and removed. Although X.509 uses BIT STRINGs
* to represent SubjectPublicKeyInfo, every key type defined encodes the key
* as a byte string with the same conversion to BIT STRING. */
int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key);
/* pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result
* to |out|. It returns one on success and zero on error. */
int (*pub_encode)(CBB *out, const EVP_PKEY *key);
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
/* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
* result into |out|. It returns one on success and zero on error. |params| is
* the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key|
* is the contents of the OCTET STRING privateKey field. */
int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key);
/* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to
* |out|. It returns one on success and zero on error. */
int (*priv_encode)(CBB *out, const EVP_PKEY *key);
/* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
* custom implementations which do not expose key material and parameters.*/
int (*pkey_opaque)(const EVP_PKEY *pk);
/* pkey_supports_digest returns one if |pkey| supports digests of
* type |md|. This is intended for use with EVP_PKEYs backing custom
* implementations which can't sign all digests. If null, it is
* assumed that all digests are supported. */
int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
int (*pkey_size)(const EVP_PKEY *pk);
int (*pkey_bits)(const EVP_PKEY *pk);
int (*param_missing)(const EVP_PKEY *pk);
int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
void (*pkey_free)(EVP_PKEY *pkey);
} /* EVP_PKEY_ASN1_METHOD */;
#define EVP_PKEY_OP_UNDEFINED 0
#define EVP_PKEY_OP_KEYGEN (1 << 2)
#define EVP_PKEY_OP_SIGN (1 << 3)
#define EVP_PKEY_OP_VERIFY (1 << 4)
#define EVP_PKEY_OP_VERIFYRECOVER (1 << 5)
#define EVP_PKEY_OP_ENCRYPT (1 << 6)
#define EVP_PKEY_OP_DECRYPT (1 << 7)
#define EVP_PKEY_OP_DERIVE (1 << 8)
#define EVP_PKEY_OP_TYPE_SIG \
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER)
#define EVP_PKEY_OP_TYPE_CRYPT (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
#define EVP_PKEY_OP_TYPE_NOGEN \
(EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
#define EVP_PKEY_OP_TYPE_GEN EVP_PKEY_OP_KEYGEN
/* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
* arguments can be -1 to specify that any type and operation are acceptable,
* otherwise |keytype| must match the type of |ctx| and the bits of |optype|
* must intersect the operation flags set on |ctx|.
*
* The |p1| and |p2| arguments depend on the value of |cmd|.
*
* It returns one on success and zero on error. */
OPENSSL_EXPORT int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2);
#define EVP_PKEY_CTRL_MD 1
#define EVP_PKEY_CTRL_GET_MD 2
/* EVP_PKEY_CTRL_PEER_KEY is called with different values of |p1|:
* 0: Is called from |EVP_PKEY_derive_set_peer| and |p2| contains a peer key.
* If the return value is <= 0, the key is rejected.
* 1: Is called at the end of |EVP_PKEY_derive_set_peer| and |p2| contains a
* peer key. If the return value is <= 0, the key is rejected.
* 2: Is called with |p2| == NULL to test whether the peer's key was used.
* (EC)DH always return one in this case.
* 3: Is called with |p2| == NULL to set whether the peer's key was used.
* (EC)DH always return one in this case. This was only used for GOST. */
#define EVP_PKEY_CTRL_PEER_KEY 3
/* EVP_PKEY_ALG_CTRL is the base value from which key-type specific ctrl
* commands are numbered. */
#define EVP_PKEY_ALG_CTRL 0x1000
#define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1)
#define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 2)
#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 3)
#define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 4)
#define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 5)
#define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 6)
#define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 7)
#define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 8)
#define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 9)
#define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 10)
#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
struct evp_pkey_ctx_st {
/* Method associated with this operation */
const EVP_PKEY_METHOD *pmeth;
/* Engine that implements this method or NULL if builtin */
ENGINE *engine;
/* Key: may be NULL */
EVP_PKEY *pkey;
/* Peer key for key agreement, may be NULL */
EVP_PKEY *peerkey;
/* operation contains one of the |EVP_PKEY_OP_*| values. */
int operation;
/* Algorithm specific data */
void *data;
} /* EVP_PKEY_CTX */;
struct evp_pkey_method_st {
int pkey_id;
int (*init)(EVP_PKEY_CTX *ctx);
int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
void (*cleanup)(EVP_PKEY_CTX *ctx);
int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
const uint8_t *tbs, size_t tbslen);
int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
const uint8_t *tbs, size_t tbslen);
int (*verify_recover)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
const uint8_t *sig, size_t sig_len);
int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen);
int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
const uint8_t *in, size_t inlen);
int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen);
int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
} /* EVP_PKEY_METHOD */;
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD ec_asn1_meth;
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meth;
extern const EVP_PKEY_METHOD rsa_pkey_meth;
extern const EVP_PKEY_METHOD ec_pkey_meth;
#if defined(__cplusplus)
} /* extern C */
#endif
#endif /* OPENSSL_HEADER_EVP_INTERNAL_H */

View File

@@ -0,0 +1,268 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
* 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <openssl/digest.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include "internal.h"
static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See RFC 3279, section 2.3.2. */
/* Parameters may or may not be present. */
DSA *dsa;
if (CBS_len(params) == 0) {
dsa = DSA_new();
if (dsa == NULL) {
return 0;
}
} else {
dsa = DSA_parse_parameters(params);
if (dsa == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
}
dsa->pub_key = BN_new();
if (dsa->pub_key == NULL) {
goto err;
}
if (!BN_parse_asn1_unsigned(key, dsa->pub_key) ||
CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
EVP_PKEY_assign_DSA(out, dsa);
return 1;
err:
DSA_free(dsa);
return 0;
}
static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
const DSA *dsa = key->pkey.dsa;
const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
/* See RFC 5480, section 2. */
CBB spki, algorithm, oid, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
(has_params &&
!DSA_marshal_parameters(&algorithm, dsa)) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
!BN_marshal_asn1(&key_bitstring, dsa->pub_key) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See PKCS#11, v2.40, section 2.5. */
/* Decode parameters. */
BN_CTX *ctx = NULL;
DSA *dsa = DSA_parse_parameters(params);
if (dsa == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
dsa->priv_key = BN_new();
dsa->pub_key = BN_new();
if (dsa->priv_key == NULL || dsa->pub_key == NULL) {
goto err;
}
/* Decode the key. */
if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
/* Calculate the public key. */
ctx = BN_CTX_new();
if (ctx == NULL ||
!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
goto err;
}
BN_CTX_free(ctx);
EVP_PKEY_assign_DSA(out, dsa);
return 1;
err:
BN_CTX_free(ctx);
DSA_free(dsa);
return 0;
}
static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
const DSA *dsa = key->pkey.dsa;
if (dsa == NULL || dsa->priv_key == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
return 0;
}
/* See PKCS#11, v2.40, section 2.5. */
CBB pkcs8, algorithm, oid, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
!DSA_marshal_parameters(&algorithm, dsa) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!BN_marshal_asn1(&private_key, dsa->priv_key) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int int_dsa_size(const EVP_PKEY *pkey) {
return DSA_size(pkey->pkey.dsa);
}
static int dsa_bits(const EVP_PKEY *pkey) {
return BN_num_bits(pkey->pkey.dsa->p);
}
static int dsa_missing_parameters(const EVP_PKEY *pkey) {
DSA *dsa;
dsa = pkey->pkey.dsa;
if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
return 1;
}
return 0;
}
static int dup_bn_into(BIGNUM **out, BIGNUM *src) {
BIGNUM *a;
a = BN_dup(src);
if (a == NULL) {
return 0;
}
BN_free(*out);
*out = a;
return 1;
}
static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
if (!dup_bn_into(&to->pkey.dsa->p, from->pkey.dsa->p) ||
!dup_bn_into(&to->pkey.dsa->q, from->pkey.dsa->q) ||
!dup_bn_into(&to->pkey.dsa->g, from->pkey.dsa->g)) {
return 0;
}
return 1;
}
static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
return BN_cmp(a->pkey.dsa->p, b->pkey.dsa->p) == 0 &&
BN_cmp(a->pkey.dsa->q, b->pkey.dsa->q) == 0 &&
BN_cmp(a->pkey.dsa->g, b->pkey.dsa->g) == 0;
}
static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
return BN_cmp(b->pkey.dsa->pub_key, a->pkey.dsa->pub_key) == 0;
}
static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
EVP_PKEY_DSA,
/* 1.2.840.10040.4.1 */
{0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
dsa_pub_decode,
dsa_pub_encode,
dsa_pub_cmp,
dsa_priv_decode,
dsa_priv_encode,
NULL /* pkey_opaque */,
NULL /* pkey_supports_digest */,
int_dsa_size,
dsa_bits,
dsa_missing_parameters,
dsa_copy_parameters,
dsa_cmp_parameters,
int_dsa_free,
};

236
external/boringssl/crypto/evp/p_ec.c vendored Normal file
View File

@@ -0,0 +1,236 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/digest.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/nid.h>
#include "internal.h"
#include "../ec/internal.h"
typedef struct {
/* message digest */
const EVP_MD *md;
} EC_PKEY_CTX;
static int pkey_ec_init(EVP_PKEY_CTX *ctx) {
EC_PKEY_CTX *dctx;
dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
if (!dctx) {
return 0;
}
memset(dctx, 0, sizeof(EC_PKEY_CTX));
ctx->data = dctx;
return 1;
}
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
EC_PKEY_CTX *dctx, *sctx;
if (!pkey_ec_init(dst)) {
return 0;
}
sctx = src->data;
dctx = dst->data;
dctx->md = sctx->md;
return 1;
}
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
EC_PKEY_CTX *dctx = ctx->data;
if (!dctx) {
return;
}
OPENSSL_free(dctx);
}
static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
const uint8_t *tbs, size_t tbslen) {
unsigned int sltmp;
EC_KEY *ec = ctx->pkey->pkey.ec;
if (!sig) {
*siglen = ECDSA_size(ec);
return 1;
} else if (*siglen < (size_t)ECDSA_size(ec)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
return 0;
}
if (!ECDSA_sign(0, tbs, tbslen, sig, &sltmp, ec)) {
return 0;
}
*siglen = (size_t)sltmp;
return 1;
}
static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
const uint8_t *tbs, size_t tbslen) {
return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec);
}
static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
size_t *keylen) {
int ret;
size_t outlen;
const EC_POINT *pubkey = NULL;
EC_KEY *eckey;
if (!ctx->pkey || !ctx->peerkey) {
OPENSSL_PUT_ERROR(EVP, EVP_R_KEYS_NOT_SET);
return 0;
}
eckey = ctx->pkey->pkey.ec;
if (!key) {
const EC_GROUP *group;
group = EC_KEY_get0_group(eckey);
*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
return 1;
}
pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
/* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is
* not an error, the result is truncated. */
outlen = *keylen;
ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
if (ret < 0) {
return 0;
}
*keylen = ret;
return 1;
}
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
EC_PKEY_CTX *dctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
*(const EVP_MD **)p2 = dctx->md;
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
/* Default behaviour is OK */
return 1;
default:
OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED);
return 0;
}
}
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
if (ctx->pkey == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
return 0;
}
EC_KEY *ec = EC_KEY_new();
if (ec == NULL ||
!EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) ||
!EC_KEY_generate_key(ec)) {
EC_KEY_free(ec);
return 0;
}
EVP_PKEY_assign_EC_KEY(pkey, ec);
return 1;
}
const EVP_PKEY_METHOD ec_pkey_meth = {
EVP_PKEY_EC,
pkey_ec_init,
pkey_ec_copy,
pkey_ec_cleanup,
pkey_ec_keygen,
pkey_ec_sign,
pkey_ec_verify,
0 /* verify_recover */,
0 /* encrypt */,
0 /* decrypt */,
pkey_ec_derive,
pkey_ec_ctrl,
};

View File

@@ -0,0 +1,257 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/ecdsa.h>
#include <openssl/err.h>
#include "internal.h"
static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
const EC_KEY *ec_key = key->pkey.ec;
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
/* See RFC 5480, section 2. */
CBB spki, algorithm, oid, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
!EC_KEY_marshal_curve_name(&algorithm, group) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
!EC_POINT_point2cbb(&key_bitstring, group, public_key,
POINT_CONVERSION_UNCOMPRESSED, NULL) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See RFC 5480, section 2. */
/* The parameters are a named curve. */
EC_POINT *point = NULL;
EC_KEY *eckey = NULL;
EC_GROUP *group = EC_KEY_parse_curve_name(params);
if (group == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
goto err;
}
eckey = EC_KEY_new();
if (eckey == NULL || !EC_KEY_set_group(eckey, group)) {
goto err;
}
point = EC_POINT_new(group);
if (point == NULL ||
!EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) ||
!EC_KEY_set_public_key(eckey, point)) {
goto err;
}
EC_GROUP_free(group);
EC_POINT_free(point);
EVP_PKEY_assign_EC_KEY(out, eckey);
return 1;
err:
EC_GROUP_free(group);
EC_POINT_free(point);
EC_KEY_free(eckey);
return 0;
}
static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
int r;
const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
*pb = EC_KEY_get0_public_key(b->pkey.ec);
r = EC_POINT_cmp(group, pa, pb, NULL);
if (r == 0) {
return 1;
} else if (r == 1) {
return 0;
} else {
return -2;
}
}
static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See RFC 5915. */
EC_GROUP *group = EC_KEY_parse_parameters(params);
if (group == NULL || CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
EC_GROUP_free(group);
return 0;
}
EC_KEY *ec_key = EC_KEY_parse_private_key(key, group);
EC_GROUP_free(group);
if (ec_key == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
EC_KEY_free(ec_key);
return 0;
}
EVP_PKEY_assign_EC_KEY(out, ec_key);
return 1;
}
static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
const EC_KEY *ec_key = key->pkey.ec;
/* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
* aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
* means. Both OpenSSL and NSS omit the redundant parameters, so we omit them
* as well. */
unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
/* See RFC 5915. */
CBB pkcs8, algorithm, oid, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
!EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int int_ec_size(const EVP_PKEY *pkey) {
return ECDSA_size(pkey->pkey.ec);
}
static int ec_bits(const EVP_PKEY *pkey) {
const EC_GROUP *group = EC_KEY_get0_group(pkey->pkey.ec);
if (group == NULL) {
ERR_clear_error();
return 0;
}
return BN_num_bits(EC_GROUP_get0_order(group));
}
static int ec_missing_parameters(const EVP_PKEY *pkey) {
return EC_KEY_get0_group(pkey->pkey.ec) == NULL;
}
static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) {
EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
if (group == NULL ||
EC_KEY_set_group(to->pkey.ec, group) == 0) {
return 0;
}
EC_GROUP_free(group);
return 1;
}
static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
*group_b = EC_KEY_get0_group(b->pkey.ec);
if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) {
/* mismatch */
return 0;
}
return 1;
}
static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
static int eckey_opaque(const EVP_PKEY *pkey) {
return EC_KEY_is_opaque(pkey->pkey.ec);
}
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
EVP_PKEY_EC,
/* 1.2.840.10045.2.1 */
{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7,
eckey_pub_decode,
eckey_pub_encode,
eckey_pub_cmp,
eckey_priv_decode,
eckey_priv_encode,
eckey_opaque,
0 /* pkey_supports_digest */,
int_ec_size,
ec_bits,
ec_missing_parameters,
ec_copy_parameters,
ec_cmp_parameters,
int_ec_free,
};

673
external/boringssl/crypto/evp/p_rsa.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,200 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
/* ====================================================================
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/rsa.h>
#include "../rsa/internal.h"
#include "internal.h"
static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
/* See RFC 3279, section 2.3.1. */
CBB spki, algorithm, oid, null, key_bitstring;
if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
!CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
!CBB_add_u8(&key_bitstring, 0 /* padding */) ||
!RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* See RFC 3279, section 2.3.1. */
/* The parameters must be NULL. */
CBS null;
if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
CBS_len(&null) != 0 ||
CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
/* Estonian IDs issued between September 2014 to September 2015 are
* broken. See https://crbug.com/532048 and https://crbug.com/534766.
*
* TODO(davidben): Switch this to the strict version in March 2016 or when
* Chromium can force client certificates down a different codepath, whichever
* comes first. */
RSA *rsa = RSA_parse_public_key_buggy(key);
if (rsa == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
RSA_free(rsa);
return 0;
}
EVP_PKEY_assign_RSA(out, rsa);
return 1;
}
static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
return BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) == 0 &&
BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
}
static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
CBB pkcs8, algorithm, oid, null, private_key;
if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
!CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
!CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
!CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
!RSA_marshal_private_key(&private_key, key->pkey.rsa) ||
!CBB_flush(out)) {
OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
return 0;
}
return 1;
}
static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
/* Per RFC 3447, A.1, the parameters have type NULL. */
CBS null;
if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
CBS_len(&null) != 0 ||
CBS_len(params) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return 0;
}
RSA *rsa = RSA_parse_private_key(key);
if (rsa == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
RSA_free(rsa);
return 0;
}
EVP_PKEY_assign_RSA(out, rsa);
return 1;
}
static int rsa_opaque(const EVP_PKEY *pkey) {
return RSA_is_opaque(pkey->pkey.rsa);
}
static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
return RSA_supports_digest(pkey->pkey.rsa, md);
}
static int int_rsa_size(const EVP_PKEY *pkey) {
return RSA_size(pkey->pkey.rsa);
}
static int rsa_bits(const EVP_PKEY *pkey) {
return BN_num_bits(pkey->pkey.rsa->n);
}
static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
EVP_PKEY_RSA,
/* 1.2.840.113549.1.1.1 */
{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9,
rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
rsa_priv_decode,
rsa_priv_encode,
rsa_opaque,
rsa_supports_digest,
int_rsa_size,
rsa_bits,
0,0,0,
int_rsa_free,
};

151
external/boringssl/crypto/evp/pbkdf.c vendored Normal file
View File

@@ -0,0 +1,151 @@
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <openssl/evp.h>
#include <string.h>
#include <openssl/hmac.h>
int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
const uint8_t *salt, size_t salt_len, unsigned iterations,
const EVP_MD *digest, size_t key_len, uint8_t *out_key) {
uint8_t digest_tmp[EVP_MAX_MD_SIZE], *p, itmp[4];
size_t cplen, mdlen, tkeylen, k;
unsigned j;
uint32_t i = 1;
HMAC_CTX hctx_tpl, hctx;
mdlen = EVP_MD_size(digest);
HMAC_CTX_init(&hctx_tpl);
p = out_key;
tkeylen = key_len;
if (!HMAC_Init_ex(&hctx_tpl, password, password_len, digest, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
while (tkeylen) {
if (tkeylen > mdlen) {
cplen = mdlen;
} else {
cplen = tkeylen;
}
/* We are unlikely to ever use more than 256 blocks (5120 bits!)
* but just in case... */
itmp[0] = (uint8_t)((i >> 24) & 0xff);
itmp[1] = (uint8_t)((i >> 16) & 0xff);
itmp[2] = (uint8_t)((i >> 8) & 0xff);
itmp[3] = (uint8_t)(i & 0xff);
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, salt, salt_len) ||
!HMAC_Update(&hctx, itmp, 4) ||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
memcpy(p, digest_tmp, cplen);
for (j = 1; j < iterations; j++) {
if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
HMAC_CTX_cleanup(&hctx_tpl);
return 0;
}
if (!HMAC_Update(&hctx, digest_tmp, mdlen) ||
!HMAC_Final(&hctx, digest_tmp, NULL)) {
HMAC_CTX_cleanup(&hctx_tpl);
HMAC_CTX_cleanup(&hctx);
return 0;
}
HMAC_CTX_cleanup(&hctx);
for (k = 0; k < cplen; k++) {
p[k] ^= digest_tmp[k];
}
}
tkeylen -= cplen;
i++;
p += cplen;
}
HMAC_CTX_cleanup(&hctx_tpl);
// RFC 2898 describes iterations (c) as being a "positive integer", so a
// value of 0 is an error.
//
// Unfortunatley not all consumers of PKCS5_PBKDF2_HMAC() check their return
// value, expecting it to succeed and unconditonally using |out_key|.
// As a precaution for such callsites in external code, the old behavior
// of iterations < 1 being treated as iterations == 1 is preserved, but
// additionally an error result is returned.
//
// TODO(eroman): Figure out how to remove this compatibility hack, or change
// the default to something more sensible like 2048.
if (iterations == 0) {
return 0;
}
return 1;
}
int PKCS5_PBKDF2_HMAC_SHA1(const char *password, size_t password_len,
const uint8_t *salt, size_t salt_len,
unsigned iterations, size_t key_len,
uint8_t *out_key) {
return PKCS5_PBKDF2_HMAC(password, password_len, salt, salt_len, iterations,
EVP_sha1(), key_len, out_key);
}

View File

@@ -0,0 +1,220 @@
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
// Prints out the data buffer as a sequence of hex bytes.
static void PrintDataHex(const void *data, size_t len) {
for (size_t i = 0; i < len; ++i) {
fprintf(stderr, "%02x", (int)((const uint8_t *)data)[i]);
}
}
// Helper for testing that PBKDF2 derives the expected key from the given
// inputs. Returns 1 on success, 0 otherwise.
static bool TestPBKDF2(const void *password, size_t password_len,
const void *salt, size_t salt_len, unsigned iterations,
const EVP_MD *digest, size_t key_len,
const uint8_t *expected_key) {
uint8_t key[64];
if (key_len > sizeof(key)) {
fprintf(stderr, "Output buffer is not large enough.\n");
return false;
}
if (!PKCS5_PBKDF2_HMAC((const char *)password, password_len,
(const uint8_t *)salt, salt_len, iterations, digest,
key_len, key)) {
fprintf(stderr, "Call to PKCS5_PBKDF2_HMAC failed\n");
ERR_print_errors_fp(stderr);
return false;
}
if (memcmp(key, expected_key, key_len) != 0) {
fprintf(stderr, "Resulting key material does not match expectation\n");
fprintf(stderr, "Expected:\n ");
PrintDataHex(expected_key, key_len);
fprintf(stderr, "\nActual:\n ");
PrintDataHex(key, key_len);
fprintf(stderr, "\n");
return false;
}
return true;
}
// Tests deriving a key using an empty password (specified both as NULL and as
// non-NULL). Note that NULL has special meaning to HMAC initialization.
static bool TestEmptyPassword() {
const uint8_t kKey[] = {0xa3, 0x3d, 0xdd, 0xc3, 0x04, 0x78, 0x18,
0x55, 0x15, 0x31, 0x1f, 0x87, 0x52, 0x89,
0x5d, 0x36, 0xea, 0x43, 0x63, 0xa2};
if (!TestPBKDF2(NULL, 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey) ||
!TestPBKDF2("", 0, "salt", 4, 1, EVP_sha1(), sizeof(kKey), kKey)) {
return false;
}
return true;
}
// Tests deriving a key using an empty salt. Note that the expectation was
// generated using OpenSSL itself, and hence is not verified.
static bool TestEmptySalt() {
const uint8_t kKey[] = {0x8b, 0xc2, 0xf9, 0x16, 0x7a, 0x81, 0xcd, 0xcf,
0xad, 0x12, 0x35, 0xcd, 0x90, 0x47, 0xf1, 0x13,
0x62, 0x71, 0xc1, 0xf9, 0x78, 0xfc, 0xfc, 0xb3,
0x5e, 0x22, 0xdb, 0xea, 0xfa, 0x46, 0x34, 0xf6};
if (!TestPBKDF2("password", 8, NULL, 0, 2, EVP_sha256(), sizeof(kKey),
kKey) ||
!TestPBKDF2("password", 8, "", 0, 2, EVP_sha256(), sizeof(kKey), kKey)) {
return false;
}
return true;
}
// Exercises test vectors taken from https://tools.ietf.org/html/rfc6070.
// Note that each of these test vectors uses SHA-1 as the digest.
static bool TestRFC6070Vectors() {
const uint8_t kKey1[] = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e,
0x71, 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60,
0x12, 0x06, 0x2f, 0xe0, 0x37, 0xa6};
const uint8_t kKey2[] = {0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f,
0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d,
0x41, 0xf0, 0xd8, 0xde, 0x89, 0x57};
const uint8_t kKey3[] = {0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3};
if (!TestPBKDF2("password", 8, "salt", 4, 1, EVP_sha1(), sizeof(kKey1),
kKey1) ||
!TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha1(), sizeof(kKey2),
kKey2) ||
!TestPBKDF2("pass\0word", 9, "sa\0lt", 5, 4096, EVP_sha1(),
sizeof(kKey3), kKey3)) {
return false;
}
return true;
}
// Tests key derivation using SHA-2 digests.
static bool TestSHA2() {
// This test was taken from:
// http://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors.
const uint8_t kKey1[] = {0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43};
// This test was taken from:
// http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors.
const uint8_t kKey2[] = {
0x8c, 0x05, 0x11, 0xf4, 0xc6, 0xe5, 0x97, 0xc6, 0xac, 0x63, 0x15,
0xd8, 0xf0, 0x36, 0x2e, 0x22, 0x5f, 0x3c, 0x50, 0x14, 0x95, 0xba,
0x23, 0xb8, 0x68, 0xc0, 0x05, 0x17, 0x4d, 0xc4, 0xee, 0x71, 0x11,
0x5b, 0x59, 0xf9, 0xe6, 0x0c, 0xd9, 0x53, 0x2f, 0xa3, 0x3e, 0x0f,
0x75, 0xae, 0xfe, 0x30, 0x22, 0x5c, 0x58, 0x3a, 0x18, 0x6c, 0xd8,
0x2b, 0xd4, 0xda, 0xea, 0x97, 0x24, 0xa3, 0xd3, 0xb8};
if (!TestPBKDF2("password", 8, "salt", 4, 2, EVP_sha256(), sizeof(kKey1),
kKey1) ||
!TestPBKDF2("passwordPASSWORDpassword", 24,
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096,
EVP_sha512(), sizeof(kKey2), kKey2)) {
return false;
}
return true;
}
// Tests key derivation using iterations=0.
//
// RFC 2898 defines the iteration count (c) as a "positive integer". So doing a
// key derivation with iterations=0 is ill-defined and should result in a
// failure.
static bool TestZeroIterations() {
static const char kPassword[] = "password";
const size_t password_len = strlen(kPassword);
static const uint8_t kSalt[] = {1, 2, 3, 4};
const size_t salt_len = sizeof(kSalt);
const EVP_MD *digest = EVP_sha1();
uint8_t key[10] = {0};
const size_t key_len = sizeof(key);
// Verify that calling with iterations=1 works.
if (!PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len,
1 /* iterations */, digest, key_len, key)) {
fprintf(stderr, "PBKDF2 failed with iterations=1\n");
return false;
}
// Flip the first key byte (so can later test if it got set).
const uint8_t expected_first_byte = key[0];
key[0] = ~key[0];
// However calling it with iterations=0 fails.
if (PKCS5_PBKDF2_HMAC(kPassword, password_len, kSalt, salt_len,
0 /* iterations */, digest, key_len, key)) {
fprintf(stderr, "PBKDF2 returned zero with iterations=0\n");
return false;
}
// For backwards compatibility, the iterations == 0 case still fills in
// the out key.
return key[0] == expected_first_byte;
}
int main(void) {
CRYPTO_library_init();
if (!TestEmptyPassword()) {
fprintf(stderr, "TestEmptyPassword failed\n");
return 1;
}
if (!TestEmptySalt()) {
fprintf(stderr, "TestEmptySalt failed\n");
return 1;
}
if (!TestRFC6070Vectors()) {
fprintf(stderr, "TestRFC6070Vectors failed\n");
return 1;
}
if (!TestSHA2()) {
fprintf(stderr, "TestSHA2 failed\n");
return 1;
}
if (!TestZeroIterations()) {
fprintf(stderr, "TestZeroIterations failed\n");
return 1;
}
printf("PASS\n");
ERR_free_strings();
return 0;
}

527
external/boringssl/crypto/evp/print.c vendored Normal file

File diff suppressed because it is too large Load Diff

151
external/boringssl/crypto/evp/sign.c vendored Normal file
View File

@@ -0,0 +1,151 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
#include <openssl/evp.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include "internal.h"
int EVP_SignInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
return EVP_DigestInit_ex(ctx, type, impl);
}
int EVP_SignInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
return EVP_DigestInit(ctx, type);
}
int EVP_SignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
return EVP_DigestUpdate(ctx, data, len);
}
int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
unsigned int *out_sig_len, EVP_PKEY *pkey) {
uint8_t m[EVP_MAX_MD_SIZE];
unsigned int m_len;
int ret = 0;
EVP_MD_CTX tmp_ctx;
EVP_PKEY_CTX *pkctx = NULL;
size_t sig_len = EVP_PKEY_size(pkey);
*out_sig_len = 0;
EVP_MD_CTX_init(&tmp_ctx);
if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
!EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
goto out;
}
EVP_MD_CTX_cleanup(&tmp_ctx);
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkctx || !EVP_PKEY_sign_init(pkctx) ||
!EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) ||
!EVP_PKEY_sign(pkctx, sig, &sig_len, m, m_len)) {
goto out;
}
*out_sig_len = sig_len;
ret = 1;
out:
if (pkctx) {
EVP_PKEY_CTX_free(pkctx);
}
return ret;
}
int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) {
return EVP_DigestInit_ex(ctx, type, impl);
}
int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type) {
return EVP_DigestInit(ctx, type);
}
int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
return EVP_DigestUpdate(ctx, data, len);
}
int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
EVP_PKEY *pkey) {
uint8_t m[EVP_MAX_MD_SIZE];
unsigned int m_len;
int ret = 0;
EVP_MD_CTX tmp_ctx;
EVP_PKEY_CTX *pkctx = NULL;
EVP_MD_CTX_init(&tmp_ctx);
if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) ||
!EVP_DigestFinal_ex(&tmp_ctx, m, &m_len)) {
EVP_MD_CTX_cleanup(&tmp_ctx);
goto out;
}
EVP_MD_CTX_cleanup(&tmp_ctx);
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkctx ||
!EVP_PKEY_verify_init(pkctx) ||
!EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest)) {
goto out;
}
ret = EVP_PKEY_verify(pkctx, sig, sig_len, m, m_len);
out:
EVP_PKEY_CTX_free(pkctx);
return ret;
}