diff --git a/Configure b/Configure index a84b5704..54225301 100755 --- a/Configure +++ b/Configure @@ -311,7 +311,8 @@ $config{sdirs} = [ "buffer", "bio", "stack", "lhash", "rand", "err", "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", "cms", "ts", "srp", "cmac", "ct", "async", "kdf", - "sm3", "sms4", "kdf2", "ecies", "ffx", "sm2", "paillier", "cpk", "otp", "gmapi", "ec2" + "sm3", "sms4", "kdf2", "ecies", "ffx", "sm2", "paillier", "cpk", "otp", "gmapi", "ec2", + "bfibe", "bb1ibe", "sm9" ]; # Known TLS and DTLS protocols diff --git a/crypto/bb1ibe/bb1ibe_asn1.c b/crypto/bb1ibe/bb1ibe_asn1.c new file mode 100644 index 00000000..84254054 --- /dev/null +++ b/crypto/bb1ibe/bb1ibe_asn1.c @@ -0,0 +1,101 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include "bb1ibe_lcl.h" + +ASN1_SEQUENCE(BB1PublicParameters) = { + ASN1_SIMPLE(BB1PublicParameters, version, LONG), + ASN1_SIMPLE(BB1PublicParameters, curve, ASN1_OBJECT), + ASN1_SIMPLE(BB1PublicParameters, p, BIGNUM), + ASN1_SIMPLE(BB1PublicParameters, q, BIGNUM), + ASN1_SIMPLE(BB1PublicParameters, pointP, FpPoint), + ASN1_SIMPLE(BB1PublicParameters, pointP1, FpPoint), + ASN1_SIMPLE(BB1PublicParameters, pointP2, FpPoint), + ASN1_SIMPLE(BB1PublicParameters, pointP3, FpPoint), + ASN1_SIMPLE(BB1PublicParameters, v, FpPoint), + ASN1_SIMPLE(BB1PublicParameters, hashfcn, ASN1_OBJECT) +} ASN1_SEQUENCE_END(BB1PublicParameters) +IMPLEMENT_ASN1_FUNCTIONS(BB1PublicParameters) +IMPLEMENT_ASN1_DUP_FUNCTION(BB1PublicParameters) + +ASN1_SEQUENCE(BB1MasterSecret) = { + ASN1_SIMPLE(BB1MasterSecret, version, LONG), + ASN1_SIMPLE(BB1MasterSecret, alpha, BIGNUM), + ASN1_SIMPLE(BB1MasterSecret, beta, BIGNUM), + ASN1_SIMPLE(BB1MasterSecret, gamma, BIGNUM) +} ASN1_SEQUENCE_END(BB1MasterSecret) +IMPLEMENT_ASN1_FUNCTIONS(BB1MasterSecret) +IMPLEMENT_ASN1_DUP_FUNCTION(BB1MasterSecret) + +ASN1_SEQUENCE(BB1PrivateKeyBlock) = { + ASN1_SIMPLE(BB1PrivateKeyBlock, version, LONG), + ASN1_SIMPLE(BB1PrivateKeyBlock, pointD0, FpPoint), + ASN1_SIMPLE(BB1PrivateKeyBlock, pointD1, FpPoint) +} ASN1_SEQUENCE_END(BB1PrivateKeyBlock) +IMPLEMENT_ASN1_FUNCTIONS(BB1PrivateKeyBlock) +IMPLEMENT_ASN1_DUP_FUNCTION(BB1PrivateKeyBlock) + +ASN1_SEQUENCE(BB1CiphertextBlock) = { + ASN1_SIMPLE(BB1CiphertextBlock, version, LONG), + ASN1_SIMPLE(BB1CiphertextBlock, pointChi0, FpPoint), + ASN1_SIMPLE(BB1CiphertextBlock, pointChi1, FpPoint), + ASN1_SIMPLE(BB1CiphertextBlock, nu, BIGNUM), + ASN1_SIMPLE(BB1CiphertextBlock, y, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(BB1CiphertextBlock) +IMPLEMENT_ASN1_FUNCTIONS(BB1CiphertextBlock) +IMPLEMENT_ASN1_DUP_FUNCTION(BB1CiphertextBlock) + diff --git a/crypto/bb1ibe/bb1ibe_err.c b/crypto/bb1ibe/bb1ibe_err.c new file mode 100644 index 00000000..8a9da30f --- /dev/null +++ b/crypto/bb1ibe/bb1ibe_err.c @@ -0,0 +1,68 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BB1IBE,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BB1IBE,0,reason) + +static ERR_STRING_DATA BB1IBE_str_functs[] = { + {ERR_FUNC(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE), + "BB1CiphertextBlock_hash_to_range"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_DECRYPT), "BB1IBE_decrypt"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_DOUBLE_HASH), "BB1IBE_double_hash"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_DO_DECRYPT), "BB1IBE_do_decrypt"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_DO_ENCRYPT), "BB1IBE_do_encrypt"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_ENCRYPT), "BB1IBE_encrypt"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY), + "BB1IBE_extract_private_key"}, + {ERR_FUNC(BB1IBE_F_BB1IBE_SETUP), "BB1IBE_setup"}, + {0, NULL} +}; + +static ERR_STRING_DATA BB1IBE_str_reasons[] = { + {ERR_REASON(BB1IBE_R_BB1CIPHERTEXT_INVALID_MAC), + "bb1ciphertext invalid mac"}, + {ERR_REASON(BB1IBE_R_BB1IBE_HASH_FAILURE), "bb1ibe hash failure"}, + {ERR_REASON(BB1IBE_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_REASON(BB1IBE_R_COMPUTE_OUTLEN_FAILURE), "compute outlen failure"}, + {ERR_REASON(BB1IBE_R_COMPUTE_TATE_FAILURE), "compute tate failure"}, + {ERR_REASON(BB1IBE_R_D2I_FAILURE), "d2i failure"}, + {ERR_REASON(BB1IBE_R_DECRYPT_FAILURE), "decrypt failure"}, + {ERR_REASON(BB1IBE_R_DOUBLE_HASH_FAILURE), "double hash failure"}, + {ERR_REASON(BB1IBE_R_ENCRYPT_FAILURE), "encrypt failure"}, + {ERR_REASON(BB1IBE_R_I2D_FAILURE), "i2d failure"}, + {ERR_REASON(BB1IBE_R_INVALID_INPUT), "invalid input"}, + {ERR_REASON(BB1IBE_R_INVALID_MD), "invalid md"}, + {ERR_REASON(BB1IBE_R_INVALID_OUTPUT_BUFFER), "invalid output buffer"}, + {ERR_REASON(BB1IBE_R_INVALID_TYPE1CURVE), "invalid type1curve"}, + {ERR_REASON(BB1IBE_R_NOT_NAMED_CURVE), "not named curve"}, + {ERR_REASON(BB1IBE_R_PARSE_PAIRING), "parse pairing"}, + {0, NULL} +}; + +#endif + +int ERR_load_BB1IBE_strings(void) +{ +#ifndef OPENSSL_NO_ERR + + if (ERR_func_error_string(BB1IBE_str_functs[0].error) == NULL) { + ERR_load_strings(0, BB1IBE_str_functs); + ERR_load_strings(0, BB1IBE_str_reasons); + } +#endif + return 1; +} diff --git a/crypto/bb1ibe/bb1ibe_lcl.h b/crypto/bb1ibe/bb1ibe_lcl.h new file mode 100644 index 00000000..2cb3dbbb --- /dev/null +++ b/crypto/bb1ibe/bb1ibe_lcl.h @@ -0,0 +1,93 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include + + +struct BB1PublicParameters_st { + long version; + ASN1_OBJECT *curve; + BIGNUM *p; + BIGNUM *q; + FpPoint *pointP; + FpPoint *pointP1; + FpPoint *pointP2; + FpPoint *pointP3; + FpPoint *v; + ASN1_OBJECT *hashfcn; +}; + +struct BB1MasterSecret_st { + long version; + BIGNUM *alpha; + BIGNUM *beta; + BIGNUM *gamma; +}; + +struct BB1PrivateKeyBlock_st { + long version; + FpPoint *pointD0; + FpPoint *pointD1; +}; + +struct BB1CiphertextBlock_st { + long version; + FpPoint *pointChi0; + FpPoint *pointChi1; + BIGNUM *nu; + ASN1_OCTET_STRING *y; +}; + diff --git a/crypto/bb1ibe/bb1ibe_lib.c b/crypto/bb1ibe/bb1ibe_lib.c new file mode 100644 index 00000000..8a79b2c5 --- /dev/null +++ b/crypto/bb1ibe/bb1ibe_lib.c @@ -0,0 +1,1013 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include "bb1ibe_lcl.h" + + +int BB1IBE_setup(const EC_GROUP *group, const EVP_MD *md, + BB1PublicParameters **pmpk, BB1MasterSecret **pmsk) +{ + int ret = 0; + BB1PublicParameters *mpk = NULL; + BB1MasterSecret *msk = NULL; + BN_CTX *bn_ctx = NULL; + EC_POINT *point = NULL; + EC_POINT *point1 = NULL; + BN_GFP2 *theta = NULL; + BIGNUM *a; + BIGNUM *b; + + if (!group || !pmpk || !pmsk) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!(bn_ctx = BN_CTX_new())) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + mpk = BB1PublicParameters_new(); + msk = BB1MasterSecret_new(); + point = EC_POINT_new(group); + point1 = EC_POINT_new(group); + theta = BN_GFP2_new(); + a = BN_CTX_get(bn_ctx); + b = BN_CTX_get(bn_ctx); + + if (!mpk || !msk || !a || !b || !point || !point1 || !theta) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * set mpk->version + * set mpk->curve + * set mpk->p + * set mpk->q + * set mpk->pointP + * set mpk->hashfcn + */ + + mpk->version = BB1IBE_VERSION; + + OPENSSL_assert(mpk->curve); + ASN1_OBJECT_free(mpk->curve); + if (!(mpk->curve = OBJ_nid2obj(NID_type1curve))) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, BB1IBE_R_NOT_NAMED_CURVE); + goto end; + } + + if (!EC_GROUP_get_curve_GFp(group, mpk->p, a, b, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + if (!EC_GROUP_get_order(group, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, EC_GROUP_get0_generator(group), + mpk->pointP->x, mpk->pointP->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, BB1IBE_R_PARSE_PAIRING); + goto end; + } + + ASN1_OBJECT_free(mpk->hashfcn); + if (!(mpk->hashfcn = OBJ_nid2obj(EVP_MD_type(md)))) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, BB1IBE_R_PARSE_PAIRING); + goto end; + } + + /* + * set msk->version + * random msk->alpha in [1, q - 1] + * random msk->beta in [1, q - 1] + * random msk->gamma in [1, q - 1] + */ + + msk->version = BB1IBE_VERSION; + + do { + if (!BN_rand_range(msk->alpha, mpk->q)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(msk->alpha)); + + do { + if (!BN_rand_range(msk->beta, mpk->q)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(msk->beta)); + + do { + if (!BN_rand_range(msk->gamma, mpk->q)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(msk->gamma)); + + /* + * mpk->pointP1 = msk->alpha * mpk->pointP + * mpk->pointP2 = msk->beta * mpk->pointP + */ + + if (!EC_POINT_mul(group, point, msk->alpha, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + mpk->pointP1->x, mpk->pointP1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_mul(group, point1, msk->beta, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point1, + mpk->pointP2->x, mpk->pointP2->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + /* + * mpk->v = e(mpk->pointP1, mpk->pointP2) in GF(p^2) + * convert pairing result from BN_GFP2 to FpPoint + */ + + if (!EC_type1curve_tate(group, theta, point, point1, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + if (!BN_copy(mpk->v->x, theta->a0)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_BN_LIB); + goto end; + } + if (!BN_copy(mpk->v->y, theta->a1)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_BN_LIB); + goto end; + } + + /* + * mpk->pointP3 = msk->gamma * mpk->pointP + * (careful: re-use tmp variable `point1` for pointP3) + */ + + if (!EC_POINT_mul(group, point, msk->gamma, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + mpk->pointP3->x, mpk->pointP3->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + *pmpk = mpk; + *pmsk = msk; + ret = 1; + +end: + if (!ret) { + BB1PublicParameters_free(mpk); + BB1MasterSecret_free(msk); + *pmpk = NULL; + *pmsk = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_POINT_free(point); + EC_POINT_free(point1); + BN_GFP2_free(theta); + return ret; +} + +BB1PrivateKeyBlock *BB1IBE_extract_private_key(BB1PublicParameters *mpk, + BB1MasterSecret *msk, const char *id, size_t idlen) +{ + int e = 1; + BB1PrivateKeyBlock *ret = NULL; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + const EVP_MD *md; + BIGNUM *r; + BIGNUM *y; + BIGNUM *hid; + + if (!mpk || !msk || !id || idlen <= 0) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!(bn_ctx = BN_CTX_new())) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* get group */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + ret = BB1PrivateKeyBlock_new(); + point = EC_POINT_new(group); + r = BN_CTX_get(bn_ctx); + y = BN_CTX_get(bn_ctx); + hid = BN_CTX_get(bn_ctx); + + if (!ret || !point || !r || !y || !hid) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* set ret->version */ + ret->version = BB1IBE_VERSION; + + /* random r in [1, q - 1] */ + do { + if (!BN_rand_range(r, mpk->q)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, + ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(r)); + + /* md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, BB1IBE_R_INVALID_MD); + goto end; + } + + /* hid = HashToRange(id), hid in [0, q - 1] */ + if (!BN_hash_to_range(md, &hid, id, idlen, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + + /* y = msk->alpha * msk->beta + r * (msk->alpha * hid + msk->gamma) in F_q + * hid = hid * msk->alpha + * hid = hid + msk->gamma + * hid = hid * r + * y = msk->alpha * msk->beta + * y = y + hid + */ + if (!BN_mod_mul(hid, hid, msk->alpha, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_add(hid, hid, msk->gamma, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_mul(hid, hid, r, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_mul(y, msk->alpha, msk->beta, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_add(y, y, hid, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + + /* sk->pointD0 = y * mpk->pointP */ + if (!EC_POINT_mul(group, point, y, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->pointD0->x, ret->pointD0->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + /* sk->pointD1 = r * mpk->pointP */ + if (!EC_POINT_mul(group, point, r, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->pointD1->x, ret->pointD1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + e = 0; + +end: + if (e && ret) { + BB1PrivateKeyBlock_free(ret); + ret = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_POINT_free(point); + return ret; +} + +/* + * return H(H(m)||m) || H(m), return length is 2*hashlen + */ +static int BB1IBE_double_hash(const EVP_MD *md, const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen) +{ + int ret = 0; + EVP_MD_CTX *ctx = NULL; + unsigned int len = EVP_MD_size(md); + + if (!md || !in || inlen <= 0 || !outlen) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (in == out) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, BB1IBE_R_INVALID_OUTPUT_BUFFER); + return 0; + } + + if (!out) { + *outlen = EVP_MD_size(md) * 2; + return 1; + } + if (*outlen < EVP_MD_size(md) * 2) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, BB1IBE_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!EVP_Digest(in, inlen, out + EVP_MD_size(md), &len, md, NULL)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_EVP_LIB); + goto end; + } + + if (!(ctx = EVP_MD_CTX_new())) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EVP_DigestInit_ex(ctx, md, NULL)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_EVP_LIB); + goto end; + } + if (!EVP_DigestUpdate(ctx, out + EVP_MD_size(md), EVP_MD_size(md))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_EVP_LIB); + goto end; + } + if (!EVP_DigestUpdate(ctx, in, inlen)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_EVP_LIB); + goto end; + } + len = EVP_MD_size(md); + if (!EVP_DigestFinal_ex(ctx, out, &len)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DOUBLE_HASH, ERR_R_EVP_LIB); + goto end; + } + + *outlen = EVP_MD_size(md) * 2; + ret = 1; +end: + EVP_MD_CTX_free(ctx); + return ret; +} + +/* + * c->u = HashToRange(DoubleHash(c->Chi0, c->Chi1, y, wbuf)) + */ +static int BB1CiphertextBlock_hash_to_range(const BB1PublicParameters *mpk, + BB1CiphertextBlock *c, const unsigned char *wbuf, size_t wbuflen, + BIGNUM *bn, BN_CTX *bn_ctx) +{ + int ret = 0; + unsigned char *buf = NULL; + unsigned char *p; + size_t buflen; + unsigned char double_hash[EVP_MAX_MD_SIZE *2]; + int pbytes; + + const EVP_MD *md; + + if (!c || !wbuf || wbuflen <= 0 || !bn || !mpk || !bn_ctx) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + return 0; + } + + + /* prepare buffer */ + pbytes = BN_num_bytes(mpk->p); + buflen = pbytes * 4 + c->y->length + wbuflen; + + if (!(buf = OPENSSL_zalloc(buflen))) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_MALLOC_FAILURE); + goto end; + } + p = buf; + + /* buf += y1 */ + if (!BN_bn2bin(c->pointChi1->y, p + pbytes - BN_num_bytes(c->pointChi1->y))) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_BN_LIB); + goto end; + } + p += pbytes; + + /* buf += x1 */ + if (!BN_bn2bin(c->pointChi1->x, p + pbytes - BN_num_bytes(c->pointChi1->x))) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_BN_LIB); + goto end; + } + p += pbytes; + + /* buf += y0 */ + if (!BN_bn2bin(c->pointChi0->y, p + pbytes - BN_num_bytes(c->pointChi0->y))) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_BN_LIB); + goto end; + } + p += pbytes; + + /* buf += x0 */ + if (!BN_bn2bin(c->pointChi0->x, p + pbytes - BN_num_bytes(c->pointChi0->x))) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_BN_LIB); + goto end; + } + p += pbytes; + + /* buf += ret->y */ + memcpy(p, c->y->data, c->y->length); + p += c->y->length; + + /* buf += wbuf */ + memcpy(p, wbuf, wbuflen); + p += wbuflen; + + OPENSSL_assert(p - buf == buflen); + + /* ret->u = HashToRange(DoubleHash(c)) */ + if (!BB1IBE_double_hash(md, buf, buflen, double_hash, &buflen)) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, BB1IBE_R_DOUBLE_HASH_FAILURE); + goto end; + } + if (!BN_hash_to_range(md, &c->nu, double_hash, buflen, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE, ERR_R_BN_LIB); + goto end; + } + + ret = 1; + +end: + OPENSSL_free(buf); + return ret; +} + +/* + * random s in [1, q - 1] + * ret->pointChi0 = mpk->pointP *s + * ret->pointChi1 = mpk->pointP1 * (s * H(ID)) + mpk->pointP3 * s + * ret->nu = HashToRange(w || Chi0 || Chi1 || y) in Zq + * ret->y = s + rho (mod q) + */ +BB1CiphertextBlock *BB1IBE_do_encrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen) +{ + int e = 1; + BB1CiphertextBlock *ret = NULL; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_POINT *point1 = NULL; + BN_GFP2 *w = NULL; + BIGNUM *s; + BIGNUM *hid; + unsigned char *wbuf = NULL; + size_t wbuflen; + unsigned char *cbuf = NULL; + const EVP_MD *md; + int i; + + if (!mpk || !in || inlen <= 0 || !id || idlen <= 0) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + goto end; + } + + if (!(bn_ctx = BN_CTX_new())) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* get group */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + ret = BB1CiphertextBlock_new(); + point = EC_POINT_new(group); + point1 = EC_POINT_new(group); + w = BN_GFP2_new(); + s = BN_CTX_get(bn_ctx); + hid = BN_CTX_get(bn_ctx); + + if (!ret || !point || !point1 || !s || !hid || !w) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* random s in [1, q - 1] */ + do { + if (!BN_rand_range(s, mpk->q)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(s)); + + /* ret->pointChi0 = mpk->pointP * s */ + if (!EC_POINT_mul(group, point, s, NULL, NULL, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->pointChi0->x, ret->pointChi0->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* get md */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + /* hid = HashToRange(id) in F_q */ + if (!BN_hash_to_range(md, &hid, id, idlen, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + /* + * ret->pointChi1 = ((mpk->pointP1 * hid) + mpk->pointP3) * s + */ + if (!EC_POINT_set_affine_coordinates_GFp(group, point, + mpk->pointP1->x, mpk->pointP1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_mul(group, point, NULL, point, hid, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point1, + mpk->pointP3->x, mpk->pointP3->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_add(group, point, point, point1, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_mul(group, point, NULL, point, s, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->pointChi1->x, ret->pointChi1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* + * w = (mpk->v)^s in F_p^2 + * w = mpk->v, convert from FpPoint to BN_GFP2 + * w = w^s + * wbuf = Canonical(w, order=1) + */ + + if (!BN_copy(w->a0, mpk->v->x)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_copy(w->a1, mpk->v->y)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + if (!BN_GFP2_exp(w, w, s, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + if (!BN_GFP2_canonical(w, NULL, &wbuflen, 1, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + if (!(wbuf = OPENSSL_malloc(wbuflen))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!BN_GFP2_canonical(w, wbuf, &wbuflen, 1, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * ret->y = HashBytes(DoubleHash(wbuf)) xor in + * DoubleHash output length == hashlen * 2 + * HashBytes output length == inlen + */ + + if (!ASN1_OCTET_STRING_set(ret->y, NULL, inlen)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + /* + //FIXME: + if (!bb1ibe_hash(md, wbuf, wbuflen, ret->y->data, inlen)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, BB1IBE_R_BB1IBE_HASH_FAILURE); + goto end; + } + */ + for (i = 0; i < inlen; i++) { + ret->y->data[i] ^= in[i]; + } + + /* + * ret->u = s + HashToRange(DoubleHash(y1||x1||y0||x0||ret->y||wbuf)) (mod q) + * (x0, y0) = ret->pointChi0 + * (x1, y1) = ret->pointChi1 + */ + + + /* ret->u += s (mod q) */ + if (!BN_mod_add(ret->nu, ret->nu, s, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + e = 0; + +end: + if (e && ret) { + BB1CiphertextBlock_free(ret); + ret = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + EC_POINT_free(point1); + BN_GFP2_free(w); + OPENSSL_free(wbuf); + OPENSSL_free(cbuf); + return ret; +} + +int BB1IBE_do_decrypt(BB1PublicParameters *mpk, + const BB1CiphertextBlock *in, unsigned char *out, size_t *outlen, + BB1PrivateKeyBlock *sk) +{ + int ret = 0; + EC_GROUP *group = NULL; + EC_POINT *point_c0 = NULL; + EC_POINT *point_c1 = NULL; + EC_POINT *point_d0 = NULL; + EC_POINT *point_d1 = NULL; + BN_CTX *bn_ctx = NULL; + BN_GFP2 *w = NULL; + BN_GFP2 *w1 = NULL; + BIGNUM *s = NULL; + BIGNUM *h = NULL; + unsigned char *wbuf = NULL; + size_t wbuflen; + size_t len; + int i; + + /* check arguments */ + if (!mpk || !in || !outlen || !sk) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + goto end; + } + + /* check output buffer */ + len = in->y->length; + if (!out) { + *outlen = len; + return 1; + } + if (*outlen < len) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, BB1IBE_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!(bn_ctx = BN_CTX_new())) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* init variables */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, BB1IBE_R_INVALID_TYPE1CURVE); + goto end; + } + + point_c0 = EC_POINT_new(group); + point_c1 = EC_POINT_new(group); + point_d0 = EC_POINT_new(group); + point_d1 = EC_POINT_new(group); + w = BN_GFP2_new(); + w1 = BN_GFP2_new(); + s = BN_CTX_get(bn_ctx); + h = BN_CTX_get(bn_ctx); + + if (!point_c0 || !point_c1 || !point_d0 || !point_d1 || !w || !w1 || !s || !h) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * w = e(in->C0, sk->D0)/e(in->C1, sk->D1) + */ + if (!EC_POINT_set_affine_coordinates_GFp(group, point_c0, + in->pointChi0->x, in->pointChi0->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, point_c1, + in->pointChi1->x, in->pointChi1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, point_d0, + sk->pointD0->x, sk->pointD0->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, point_d1, + sk->pointD1->x, sk->pointD1->y, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_type1curve_tate_ratio(group, w, point_c0, point_d0, + point_c1, point_d1, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, BB1IBE_R_COMPUTE_TATE_FAILURE); + goto end; + } + + /* wbuf = Canonical(w, order=1) */ + if (!BN_GFP2_canonical(w, NULL, &wbuflen, 1, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!(wbuf = OPENSSL_malloc(wbuflen))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!BN_GFP2_canonical(w, wbuf, &wbuflen, 1, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* h = H(ciphertext||w) */ + if (!BB1CiphertextBlock_hash_to_range(mpk, in, wbuf, wbuflen, h, bn_ctx)) { + goto end; + } + + + /* s = in->nu - H(c) */ + if (!BN_mod_sub(s, in->nu, h, mpk->q, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + + /* check if w == v^s */ + if (!BN_copy(w1->a0, mpk->v->x)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_copy(w1->a1, mpk->v->y)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_GFP2_exp(w1, w1, s, mpk->p, bn_ctx)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (BN_GFP2_cmp(w, w1) != 0) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, BB1IBE_R_BB1CIPHERTEXT_INVALID_MAC); + goto end; + } + + /* + * out = HashBytes(DoubleHash(wbuf)) xor in->y + */ + /* + if (!bb1ibe_hash(md, wbuf, wbuflen, out, in->y->length)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DO_DECRYPT, BB1IBE_R_BB1IBE_HASH_FAILURE); + goto end; + } + */ + for (i = 0; i < in->y->length; i++) { + out[i] ^= in->y->data[i]; + } + + ret = 1; +end: + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point_c0); + EC_POINT_free(point_c1); + EC_POINT_free(point_d0); + EC_POINT_free(point_d1); + BN_GFP2_free(w); + BN_GFP2_free(w1); + OPENSSL_free(wbuf); + return ret; +} + +static int BB1PublicParameters_size(BB1PublicParameters *mpk, + size_t inlen, size_t *outlen) +{ + size_t len = 0; + len += (OPENSSL_ECC_MAX_FIELD_BITS/8) * 5; + len += inlen; + len += EVP_MAX_MD_SIZE; + len += 256; /* caused by version and DER encoding */ + *outlen = len; + return 1; +} + +int BB1IBE_encrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen) +{ + int ret = 0; + BB1CiphertextBlock *c = NULL; + unsigned char *p; + size_t len; + + if (!mpk || !in || inlen <= 0 || !outlen || !id || idlen <= 0) { + BB1IBEerr(BB1IBE_F_BB1IBE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!BB1PublicParameters_size(mpk, inlen, &len)) { + BB1IBEerr(BB1IBE_F_BB1IBE_ENCRYPT, BB1IBE_R_COMPUTE_OUTLEN_FAILURE); + return 0; + } + if (!out) { + *outlen = len; + return 1; + } + if (*outlen < len) { + BB1IBEerr(BB1IBE_F_BB1IBE_ENCRYPT, BB1IBE_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!(c = BB1IBE_do_encrypt(mpk, in, inlen, id, idlen))) { + BB1IBEerr(BB1IBE_F_BB1IBE_ENCRYPT, BB1IBE_R_ENCRYPT_FAILURE); + goto end; + } + + p = out; + if (!i2d_BB1CiphertextBlock(c, &p)) { + BB1IBEerr(BB1IBE_F_BB1IBE_ENCRYPT, BB1IBE_R_I2D_FAILURE); + goto end; + } + len = p - out; + + *outlen = len; + ret = 1; + +end: + BB1CiphertextBlock_free(c); + return ret; +} + +int BB1IBE_decrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + BB1PrivateKeyBlock *sk) +{ + int ret = 0; + BB1CiphertextBlock *c = NULL; + const unsigned char *p; + + if (!mpk || !in || inlen <= 0 || !outlen || !sk) { + BB1IBEerr(BB1IBE_F_BB1IBE_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!out) { + *outlen = inlen; + return 1; + } + if (*outlen < inlen) { + BB1IBEerr(BB1IBE_F_BB1IBE_DECRYPT, BB1IBE_R_BUFFER_TOO_SMALL); + return 0; + } + + p = in; + if (!(c = d2i_BB1CiphertextBlock(NULL, &p, inlen))) { + BB1IBEerr(BB1IBE_F_BB1IBE_DECRYPT, BB1IBE_R_D2I_FAILURE); + goto end; + } + + /* check that all input has been decoded */ + if (p - in != inlen) { + BB1IBEerr(BB1IBE_F_BB1IBE_DECRYPT, BB1IBE_R_INVALID_INPUT); + goto end; + } + + if (!BB1IBE_do_decrypt(mpk, c, out, outlen, sk)) { + BB1IBEerr(BB1IBE_F_BB1IBE_DECRYPT, BB1IBE_R_DECRYPT_FAILURE); + goto end; + } + + ret = 1; +end: + BB1CiphertextBlock_free(c); + return ret; +} + diff --git a/crypto/bb1ibe/build.info b/crypto/bb1ibe/build.info new file mode 100644 index 00000000..eb25a88a --- /dev/null +++ b/crypto/bb1ibe/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=bb1ibe_err.c bb1ibe_asn1.c bb1ibe_lib.c diff --git a/crypto/bfibe/bfibe_asn1.c b/crypto/bfibe/bfibe_asn1.c new file mode 100644 index 00000000..8abfa1f3 --- /dev/null +++ b/crypto/bfibe/bfibe_asn1.c @@ -0,0 +1,100 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bfibe_lcl.h" + +ASN1_SEQUENCE(BFPublicParameters) = { + ASN1_SIMPLE(BFPublicParameters, version, LONG), + ASN1_SIMPLE(BFPublicParameters, curve, ASN1_OBJECT), + ASN1_SIMPLE(BFPublicParameters, p, BIGNUM), + ASN1_SIMPLE(BFPublicParameters, q, BIGNUM), + ASN1_SIMPLE(BFPublicParameters, pointP, FpPoint), + ASN1_SIMPLE(BFPublicParameters, pointPpub, FpPoint), + ASN1_SIMPLE(BFPublicParameters, hashfcn, ASN1_OBJECT) +} ASN1_SEQUENCE_END(BFPublicParameters) +IMPLEMENT_ASN1_FUNCTIONS(BFPublicParameters) +IMPLEMENT_ASN1_DUP_FUNCTION(BFPublicParameters) + +ASN1_SEQUENCE(BFMasterSecret) = { + ASN1_SIMPLE(BFMasterSecret, version, LONG), + ASN1_SIMPLE(BFMasterSecret, masterSecret, BIGNUM) +} ASN1_SEQUENCE_END(BFMasterSecret) +IMPLEMENT_ASN1_FUNCTIONS(BFMasterSecret) +IMPLEMENT_ASN1_DUP_FUNCTION(BFMasterSecret) + +ASN1_SEQUENCE(BFPrivateKeyBlock) = { + ASN1_SIMPLE(BFPrivateKeyBlock, version, LONG), + ASN1_SIMPLE(BFPrivateKeyBlock, privateKey, FpPoint) +} ASN1_SEQUENCE_END(BFPrivateKeyBlock) +IMPLEMENT_ASN1_FUNCTIONS(BFPrivateKeyBlock) +IMPLEMENT_ASN1_DUP_FUNCTION(BFPrivateKeyBlock) + +ASN1_SEQUENCE(BFCiphertextBlock) = { + ASN1_SIMPLE(BFCiphertextBlock, version, LONG), + ASN1_SIMPLE(BFCiphertextBlock, u, FpPoint), + ASN1_SIMPLE(BFCiphertextBlock, v, ASN1_OCTET_STRING), + ASN1_SIMPLE(BFCiphertextBlock, w, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(BFCiphertextBlock) +IMPLEMENT_ASN1_FUNCTIONS(BFCiphertextBlock) +IMPLEMENT_ASN1_DUP_FUNCTION(BFCiphertextBlock) + diff --git a/crypto/bfibe/bfibe_err.c b/crypto/bfibe/bfibe_err.c new file mode 100644 index 00000000..01057417 --- /dev/null +++ b/crypto/bfibe/bfibe_err.c @@ -0,0 +1,66 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BFIBE,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BFIBE,0,reason) + +static ERR_STRING_DATA BFIBE_str_functs[] = { + {ERR_FUNC(BFIBE_F_BFIBE_DECRYPT), "BFIBE_decrypt"}, + {ERR_FUNC(BFIBE_F_BFIBE_DO_DECRYPT), "BFIBE_do_decrypt"}, + {ERR_FUNC(BFIBE_F_BFIBE_DO_ENCRYPT), "BFIBE_do_encrypt"}, + {ERR_FUNC(BFIBE_F_BFIBE_ENCRYPT), "BFIBE_encrypt"}, + {ERR_FUNC(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY), + "BFIBE_extract_private_key"}, + {ERR_FUNC(BFIBE_F_BFIBE_SETUP), "BFIBE_setup"}, + {0, NULL} +}; + +static ERR_STRING_DATA BFIBE_str_reasons[] = { + {ERR_REASON(BFIBE_R_BFIBE_CIPHERTEXT_FAILURE), + "bfibe ciphertext failure"}, + {ERR_REASON(BFIBE_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_REASON(BFIBE_R_COMPUTE_OUTLEN_FAILURE), "compute outlen failure"}, + {ERR_REASON(BFIBE_R_D2I_FAILURE), "d2i failure"}, + {ERR_REASON(BFIBE_R_DECRYPT_FAILURE), "decrypt failure"}, + {ERR_REASON(BFIBE_R_ENCRYPT_FAILURE), "encrypt failure"}, + {ERR_REASON(BFIBE_R_HASH_BYTES_FAILURE), "hash bytes failure"}, + {ERR_REASON(BFIBE_R_I2D_FAILURE), "i2d failure"}, + {ERR_REASON(BFIBE_R_INVALID_BFIBE_HASHFUNC), "invalid bfibe hashfunc"}, + {ERR_REASON(BFIBE_R_INVALID_CIPHERTEXT), "invalid ciphertext"}, + {ERR_REASON(BFIBE_R_INVALID_TYPE1CURVE), "invalid type1curve"}, + {ERR_REASON(BFIBE_R_KDF_FAILURE), "kdf failure"}, + {ERR_REASON(BFIBE_R_NOT_NAMED_CURVE), "not named curve"}, + {ERR_REASON(BFIBE_R_PARSE_CURVE_FAILURE), "parse curve failure"}, + {ERR_REASON(BFIBE_R_PARSE_MPK_FAILURE), "parse mpk failure"}, + {ERR_REASON(BFIBE_R_PARSE_PAIRING), "parse pairing"}, + {ERR_REASON(BFIBE_R_RAND_FAILURE), "rand failure"}, + {0, NULL} +}; + +#endif + +int ERR_load_BFIBE_strings(void) +{ +#ifndef OPENSSL_NO_ERR + + if (ERR_func_error_string(BFIBE_str_functs[0].error) == NULL) { + ERR_load_strings(0, BFIBE_str_functs); + ERR_load_strings(0, BFIBE_str_reasons); + } +#endif + return 1; +} diff --git a/crypto/bfibe/bfibe_lcl.h b/crypto/bfibe/bfibe_lcl.h new file mode 100644 index 00000000..3aa268cc --- /dev/null +++ b/crypto/bfibe/bfibe_lcl.h @@ -0,0 +1,102 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * the `curve` attribute of BFPublicParameters is the OID present the + * `type1curve` which is E: y^2 = x^3 + 1 over prime field. It is not an + * elliptic curve domain parameters composed of (p, a, b, G, n, h). + * For type-1 curve, a = 0, b = 1. + * q (i.e. the n in ec params) is the order of generator G, is a prime. + * When q is a solinas prime, the scalar mulitiplication computation can + * be reduced. + * zeta (i.e. h in ec params) = (p + 1)/q. In normall ecc, h is very small + * such as 1 or 4. But in pairing, the zeta (or h) is very large. + */ +struct BFPublicParameters_st { + long version; + ASN1_OBJECT *curve; + BIGNUM *p; + BIGNUM *q; + FpPoint *pointP; + FpPoint *pointPpub; + ASN1_OBJECT *hashfcn; +}; + +struct BFMasterSecret_st { + long version; + BIGNUM *masterSecret; +}; + +struct BFPrivateKeyBlock_st { + long version; + FpPoint *privateKey; +}; + +struct BFCiphertextBlock_st { + long version; + FpPoint *u; + ASN1_OCTET_STRING *v; + ASN1_OCTET_STRING *w; +}; + diff --git a/crypto/bfibe/bfibe_lib.c b/crypto/bfibe/bfibe_lib.c new file mode 100644 index 00000000..32256411 --- /dev/null +++ b/crypto/bfibe/bfibe_lib.c @@ -0,0 +1,710 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bfibe_lcl.h" + + +int BFIBE_setup(const EC_GROUP *group, const EVP_MD *md, + BFPublicParameters **pmpk, BFMasterSecret **pmsk) +{ + int ret = 0; + BFPublicParameters *mpk = NULL; + BFMasterSecret *msk = NULL; + BN_CTX *bn_ctx = NULL; + EC_POINT *point = NULL; + BIGNUM *a; + BIGNUM *b; + + if (!group || !pmpk || !pmsk) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!(bn_ctx = BN_CTX_new())) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); + goto end; + } + + BN_CTX_start(bn_ctx); + a = BN_CTX_get(bn_ctx); + b = BN_CTX_get(bn_ctx); + if (!b) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); + goto end; + } + + mpk = BFPublicParameters_new(); + msk = BFMasterSecret_new(); + point = EC_POINT_new(group); + + if (!mpk || !msk || !point) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * set mpk->version + * set mpk->curve + */ + + mpk->version = BFIBE_VERSION; + + OPENSSL_assert(mpk->curve); + ASN1_OBJECT_free(mpk->curve); + if (!(mpk->curve = OBJ_nid2obj(NID_type1curve))) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_NOT_NAMED_CURVE); + goto end; + } + + /* mpk->p = group->p */ + if (!EC_GROUP_get_curve_GFp(group, mpk->p, a, b, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); + goto end; + } + if (!BN_is_zero(a) || !BN_is_one(b)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_INVALID_TYPE1CURVE); + goto end; + } + + /* mpk->q = group->order */ + if (!EC_GROUP_get_order(group, mpk->q, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_INVALID_TYPE1CURVE); + goto end; + } + + /* mpk->pointP = group->generator */ + if (!EC_POINT_get_affine_coordinates_GFp(group, EC_GROUP_get0_generator(group), + mpk->pointP->x, mpk->pointP->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + /* set mpk->hashfcn from F_p^2 element bits */ + OPENSSL_assert(mpk->hashfcn); + ASN1_OBJECT_free(mpk->hashfcn); + if (!(mpk->hashfcn = OBJ_nid2obj(EVP_MD_type(md)))) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, BFIBE_R_PARSE_PAIRING); + goto end; + } + + /* + * set msk->version + * random msk->masterSecret in [2, q - 1] + */ + + msk->version = BFIBE_VERSION; + + do { + if (!BN_rand_range(msk->masterSecret, mpk->q)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(msk->masterSecret) || BN_is_one(msk->masterSecret)); + + /* mpk->pointPpub = msk->masterSecret * mpk->pointP */ + + if (!EC_POINT_mul(group, point, msk->masterSecret, NULL, NULL, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + mpk->pointPpub->x, mpk->pointPpub->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_SETUP, ERR_R_EC_LIB); + goto end; + } + + /* set return value */ + *pmpk = mpk; + *pmsk = msk; + ret = 1; + +end: + if (!ret) { + BFPublicParameters_free(mpk); + BFMasterSecret_free(msk); + *pmpk = NULL; + *pmsk = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_POINT_free(point); + return ret; +} + +BFPrivateKeyBlock *BFIBE_extract_private_key(BFPublicParameters *mpk, + BFMasterSecret *msk, const char *id, size_t idlen) +{ + int e = 1; + BFPrivateKeyBlock *ret = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + BN_CTX *bn_ctx = NULL; + const EVP_MD *md; + + if (!mpk || !msk || !id || idlen <= 0) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (!(bn_ctx = BN_CTX_new())) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, + ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * get EC_GROUP from mpk->{p, q, pointP} + * get EVP_MD from mpk->hashfcn + */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, BFIBE_R_PARSE_CURVE_FAILURE); + goto end; + } + + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, + BFIBE_R_INVALID_BFIBE_HASHFUNC); + goto end; + } + + /* prepare tmp variables */ + point = EC_POINT_new(group); + if (!point) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* + * set ret->version + * set ret->privateKey = msk->masterSecret * HashToPoint(ID) + */ + + if (!(ret = BFPrivateKeyBlock_new())) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ret->version = BFIBE_VERSION; + + if (!EC_POINT_hash2point(group, md, id, idlen, point, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_mul(group, point, NULL, point, msk->masterSecret, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->privateKey->x, ret->privateKey->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + e = 0; +end: + if (e && ret) { + BFPrivateKeyBlock_free(ret); + ret = NULL; + } + EC_GROUP_free(group); + EC_POINT_free(point); + BN_CTX_free(bn_ctx); + return ret; +} + +/* + * r = rand(), |r| = hashlen + * k = HashToRange(r||Hash(m), q), k in [0, q-1] + * U = [k]P in E/F_p + * Q = HashToPoint(ID) in E/F_p + * v = Hash(e(Ppub, Q)^k) xor r, |v| == hashlen + * w = HashBytes(r) xor m + */ +BFCiphertextBlock *BFIBE_do_encrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen) +{ + int e = 1; + BFCiphertextBlock *ret = NULL; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *Ppub = NULL; + EC_POINT *point = NULL; + BN_GFP2 *theta = NULL; + BIGNUM *k; + const EVP_MD *md; + KDF_FUNC hash_bytes; + unsigned char rho[EVP_MAX_MD_SIZE * 2]; + unsigned char buf[EVP_MAX_MD_SIZE]; + unsigned int len; + size_t size; + int i; + + if (!mpk || !in || inlen <= 0 || !id || idlen <= 0) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, BFIBE_R_PARSE_MPK_FAILURE); + goto end; + } + + ret = BFCiphertextBlock_new(); + Ppub = EC_POINT_new(group); + point = EC_POINT_new(group); + theta = BN_GFP2_new(); + k = BN_CTX_get(bn_ctx); + + if (!ret || !point || !Ppub || !k || !theta) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + + /* get kdf from mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, BFIBE_R_INVALID_BFIBE_HASHFUNC); + goto end; + } + + if (!(hash_bytes = KDF_get_ibcs(md))) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, + BFIBE_R_INVALID_BFIBE_HASHFUNC); + goto end; + } + + /* ret->version */ + ret->version = BFIBE_VERSION; + + /* rho = Rand(hashlen) */ + if (!RAND_bytes(rho, EVP_MD_size(md))) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, BFIBE_R_RAND_FAILURE); + goto end; + } + + /* k = HashToRange(rho||Hash(in), q) in [0, q - 1] */ + len = EVP_MD_size(md); + if (!EVP_Digest(in, inlen, rho + EVP_MD_size(md), &len, md, NULL)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EVP_LIB); + goto end; + } + if (!BN_hash_to_range(md, &k, rho, EVP_MD_size(md) * 2, mpk->q, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + /* ret->u = mpk->pointP * k in E/F_p, mpk->pointP is the generator */ + if (!EC_POINT_mul(group, point, k, NULL, NULL, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_get_affine_coordinates_GFp(group, point, + ret->u->x, ret->u->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* theta = e(mpk->pointPpub, HashToPoint(ID)) */ + if (!EC_POINT_set_affine_coordinates_GFp(group, Ppub, + mpk->pointPpub->x, mpk->pointPpub->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_hash2point(group, md, id, idlen, point, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_type1curve_tate(group, theta, Ppub, point, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* theta = theta^k */ + if (!BN_GFP2_exp(theta, theta, k, mpk->p, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EC_LIB); + goto end; + } + + /* ret->v = Hash(theta) xor rho */ + size = sizeof(buf); + if (!BN_GFP2_canonical(theta, buf, &size, 0, mpk->p, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + len = sizeof(buf); + if (!EVP_Digest(buf, size, buf, &len, md, NULL)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_EVP_LIB); + goto end; + } + for (i = 0; i < EVP_MD_size(md); i++) { + buf[i] ^= rho[i]; + } + if (!ASN1_OCTET_STRING_set(ret->v, buf, EVP_MD_size(md))) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_ASN1_LIB); + goto end; + } + + /* ret->w = HashBytes(rho) xor m */ + if (!ASN1_OCTET_STRING_set(ret->w, NULL, inlen)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + size = inlen; + if (!hash_bytes(rho, EVP_MD_size(md), ret->w->data, &size)) { + BFIBEerr(BFIBE_F_BFIBE_DO_ENCRYPT, + BFIBE_R_HASH_BYTES_FAILURE); + goto end; + } + for (i = 0; i < inlen; i++) { + ret->w->data[i] ^= in[i]; + } + + e = 0; + +end: + if (e && ret) { + BFCiphertextBlock_free(ret); + ret = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(Ppub); + EC_POINT_free(point); + BN_GFP2_free(theta); + return ret; +} + +int BFIBE_do_decrypt(BFPublicParameters *mpk, + const BFCiphertextBlock *in, unsigned char *out, size_t *outlen, + BFPrivateKeyBlock *sk) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_POINT *point1 = NULL; + BN_GFP2 *theta = NULL; + BIGNUM *k; + const EVP_MD *md; + KDF_FUNC hash_bytes; + unsigned char rho[EVP_MAX_MD_SIZE * 2]; + unsigned int size; + int i; + + if (!mpk || !in || !outlen || !sk) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!out) { + *outlen = in->w->length; + return 1; + } + if (*outlen < in->w->length) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, + BFIBE_R_BUFFER_TOO_SMALL); + return 0; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve(mpk->p, mpk->pointP->x, + mpk->pointP->y, mpk->q, bn_ctx))) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, + BFIBE_R_INVALID_TYPE1CURVE); + goto end; + } + + point = EC_POINT_new(group); + point1 = EC_POINT_new(group); + theta = BN_GFP2_new(); + k = BN_CTX_get(bn_ctx); + + if (!point || !point1 || !theta || !k) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* theta = e(ciphertext->u, sk->privateKey) */ + if (!EC_POINT_set_affine_coordinates_GFp(group, point, + in->u->x, in->u->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, point1, + sk->privateKey->x, sk->privateKey->y, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EC_type1curve_tate(group, theta, point, point1, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + + /* md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, BFIBE_R_INVALID_BFIBE_HASHFUNC); + goto end; + } + + /* rho = Hash(Canoncial(theta)) xor ciphertext->v */ + size = sizeof(rho); + if (!BN_GFP2_canonical(theta, rho, &size, 0, mpk->p, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (!EVP_Digest(rho, size, rho, &size, md, NULL)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EVP_LIB); + goto end; + } + for (i = 0; i < EVP_MD_size(md); i++) { + rho[i] ^= in->v->data[i]; + } + + /* function hash_bytes() = kdf(md) */ + if (!(hash_bytes = KDF_get_ibcs(md))) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, + BFIBE_R_INVALID_BFIBE_HASHFUNC); + goto end; + } + + /* out = HashBytes(rho) xor ciphertext->w */ + size = in->w->length; + if (!hash_bytes(rho, EVP_MD_size(md), out, &size)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, + BFIBE_R_KDF_FAILURE); + goto end; + } + for (i = 0; i < in->w->length; i++) { + out[i] ^= in->w->data[i]; + } + + /* k = HashToRange(rho || Hash(out)) in [0, mpk->q) */ + size = EVP_MD_size(md); + if (!EVP_Digest(out, in->w->length, rho + EVP_MD_size(md), &size, md, NULL)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EVP_LIB); + goto end; + } + if (!BN_hash_to_range(md, &k, rho, EVP_MD_size(md) * 2, mpk->q, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_BN_LIB); + goto end; + } + + /* Verify that in->u == mpk->pointP * k */ + if (!EC_POINT_mul(group, point, k, NULL, NULL, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, ERR_R_EC_LIB); + goto end; + } + if (1 != EC_POINT_cmp_fppoint(group, point, in->u, bn_ctx)) { + BFIBEerr(BFIBE_F_BFIBE_DO_DECRYPT, BFIBE_R_BFIBE_CIPHERTEXT_FAILURE); + goto end; + } + + *outlen = in->w->length; + ret = 1; + +end: + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + EC_POINT_free(point1); + BN_GFP2_free(theta); + return ret; +} + +/* estimation of the max length of DER encoded ciphertext */ +static int BFCiphertextBlock_size(BFPublicParameters *mpk, + size_t inlen, size_t *outlen) +{ + size_t len = 0; + len += (OPENSSL_ECC_MAX_FIELD_BITS/8) * 2; + len += inlen; + len += EVP_MAX_MD_SIZE; + len += 128; /* caused by version and DER encoding */ + *outlen = len; + return 1; +} + +int BFIBE_encrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen) +{ + int ret = 0; + BFCiphertextBlock *c = NULL; + unsigned char *p; + size_t len; + + if (!mpk || !in || inlen <= 0 || !outlen || !id || idlen <= 0) { + BFIBEerr(BFIBE_F_BFIBE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!BFCiphertextBlock_size(mpk, inlen, &len)) { + BFIBEerr(BFIBE_F_BFIBE_ENCRYPT, BFIBE_R_COMPUTE_OUTLEN_FAILURE); + return 0; + } + if (!out) { + *outlen = len; + return 1; + } + if (*outlen < len) { + BFIBEerr(BFIBE_F_BFIBE_ENCRYPT, BFIBE_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!(c = BFIBE_do_encrypt(mpk, in, inlen, id, idlen))) { + BFIBEerr(BFIBE_F_BFIBE_ENCRYPT, BFIBE_R_ENCRYPT_FAILURE); + goto end; + } + + p = out; + if (!i2d_BFCiphertextBlock(c, &p)) { + BFIBEerr(BFIBE_F_BFIBE_ENCRYPT, BFIBE_R_I2D_FAILURE); + goto end; + } + len = p - out; + + *outlen = len; + ret = 1; + +end: + BFCiphertextBlock_free(c); + return ret; +} + +int BFIBE_decrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + BFPrivateKeyBlock *sk) +{ + int ret = 0; + BFCiphertextBlock *c = NULL; + const unsigned char *p; + + if (!mpk || !in || inlen <= 0 || !outlen || !sk) { + BFIBEerr(BFIBE_F_BFIBE_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!out) { + *outlen = inlen; + return 1; + } + if (*outlen < inlen) { + BFIBEerr(BFIBE_F_BFIBE_DECRYPT, BFIBE_R_BUFFER_TOO_SMALL); + return 0; + } + + p = in; + if (!(c = d2i_BFCiphertextBlock(NULL, &p, inlen))) { + BFIBEerr(BFIBE_F_BFIBE_DECRYPT, BFIBE_R_D2I_FAILURE); + goto end; + } + + /* check no remaining ciphertext */ + if (p - in != inlen) { + BFIBEerr(BFIBE_F_BFIBE_DECRYPT, BFIBE_R_INVALID_CIPHERTEXT); + goto end; + } + + if (!BFIBE_do_decrypt(mpk, c, out, outlen, sk)) { + BFIBEerr(BFIBE_F_BFIBE_DECRYPT, BFIBE_R_DECRYPT_FAILURE); + goto end; + } + + ret = 1; +end: + BFCiphertextBlock_free(c); + return ret; +} + diff --git a/crypto/bfibe/build.info b/crypto/bfibe/build.info new file mode 100644 index 00000000..692d02c5 --- /dev/null +++ b/crypto/bfibe/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=bfibe_err.c bfibe_asn1.c bfibe_lib.c diff --git a/crypto/err/err.c b/crypto/err/err.c index 7fdc2b4f..86b356ce 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -65,6 +65,9 @@ static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_CPK, 0, 0), "CPK routines"}, {ERR_PACK(ERR_LIB_OTP, 0, 0), "OTP routines"}, {ERR_PACK(ERR_LIB_GMAPI, 0, 0), "GMAPI routines"}, + {ERR_PACK(ERR_LIB_BFIBE, 0, 0), "BFIBE routines"}, + {ERR_PACK(ERR_LIB_BB1IBE, 0, 0), "BB1IBE routines"}, + {ERR_PACK(ERR_LIB_SM9, 0, 0), "SM9 routines"}, {0, NULL}, }; @@ -115,6 +118,9 @@ static ERR_STRING_DATA ERR_str_reasons[] = { {ERR_R_CPK_LIB, "CPK lib"}, {ERR_R_OTP_LIB, "OTP lib"}, {ERR_R_GMAPI_LIB, "GMAPI lib"}, + {ERR_R_BFIBE_LIB, "BFIBE lib"}, + {ERR_R_BB1IBE_LIB, "BB1IBE lib"}, + {ERR_R_SM9_LIB, "SM9 lib"}, {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"}, {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"}, diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c index 12bf302f..900bd6a0 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -45,6 +45,9 @@ #include #include #include +#include +#include +#include int err_load_crypto_strings_int(void) { @@ -125,6 +128,15 @@ int err_load_crypto_strings_int(void) # ifndef OPENSSL_NO_GMAPI ERR_load_GMAPI_strings() == 0 || # endif +# ifndef OPENSSL_NO_BFIBE + ERR_load_BFIBE_strings() == 0 || +# endif +# ifndef OPENSSL_NO_BB1IBE + ERR_load_BB1IBE_strings() == 0 || +# endif +# ifndef OPENSSL_NO_SM9 + ERR_load_SM9_strings() == 0 || +# endif #endif ERR_load_KDF_strings() == 0) return 0; diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index 8988a842..87a2a45f 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -41,6 +41,9 @@ L PAILLIER include/openssl/paillier.h crypto/paillier/pai_err.c L CPK include/openssl/cpk.h crypto/cpk/cpk_err.c L OTP include/openssl/otp.h crypto/otp/otp_err.c L GMAPI include/openssl/gmapi.h crypto/gmapi/gmapi_err.c +L BFIBE include/openssl/bfibe.h crypto/bfibe/bfibe_err.c +L BB1IBE include/openssl/bb1ibe.h crypto/bb1ibe/bb1ibe_err.c +L SM9 include/openssl/sm9.h crypto/sm9/sm9_err.c # additional header files to be scanned for function names L NONE crypto/x509/x509_vfy.h NONE diff --git a/crypto/sm9/build.info b/crypto/sm9/build.info new file mode 100644 index 00000000..4d9af353 --- /dev/null +++ b/crypto/sm9/build.info @@ -0,0 +1,3 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=sm9_lib.c sm9_err.c sm9_asn1.c sm9_params.c \ + sm9_setup.c sm9_keygen.c sm9_sign.c sm9_enc.c sm9_kap.c diff --git a/crypto/sm9/sm9_asn1.c b/crypto/sm9/sm9_asn1.c new file mode 100644 index 00000000..79f852b6 --- /dev/null +++ b/crypto/sm9/sm9_asn1.c @@ -0,0 +1,104 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include "sm9_lcl.h" + +ASN1_SEQUENCE(SM9PublicParameters) = { + ASN1_SIMPLE(SM9PublicParameters, curve, ASN1_OBJECT), + ASN1_SIMPLE(SM9PublicParameters, p, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, a, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, b, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, beta, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, order, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, cofactor, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, k, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, pointP1, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM9PublicParameters, pointP2, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM9PublicParameters, pairing, ASN1_OBJECT), + ASN1_SIMPLE(SM9PublicParameters, pointPpub, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM9PublicParameters, g1, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, g2, BIGNUM), + ASN1_SIMPLE(SM9PublicParameters, hashfcn, ASN1_OBJECT) +} ASN1_SEQUENCE_END(SM9PublicParameters) +IMPLEMENT_ASN1_FUNCTIONS(SM9PublicParameters) +IMPLEMENT_ASN1_DUP_FUNCTION(SM9PublicParameters) + +ASN1_SEQUENCE(SM9MasterSecret) = { + ASN1_SIMPLE(SM9MasterSecret, masterSecret, BIGNUM) +} ASN1_SEQUENCE_END(SM9MasterSecret) +IMPLEMENT_ASN1_FUNCTIONS(SM9MasterSecret) +IMPLEMENT_ASN1_DUP_FUNCTION(SM9MasterSecret) + +ASN1_SEQUENCE(SM9PrivateKey) = { + ASN1_SIMPLE(SM9PrivateKey, privatePoint, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SM9PrivateKey) +IMPLEMENT_ASN1_FUNCTIONS(SM9PrivateKey) +IMPLEMENT_ASN1_DUP_FUNCTION(SM9PrivateKey) + +ASN1_SEQUENCE(SM9Ciphertext) = { + ASN1_SIMPLE(SM9Ciphertext, pointC1, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM9Ciphertext, c2, ASN1_OCTET_STRING), + ASN1_SIMPLE(SM9Ciphertext, c3, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SM9Ciphertext) +IMPLEMENT_ASN1_FUNCTIONS(SM9Ciphertext) +IMPLEMENT_ASN1_DUP_FUNCTION(SM9Ciphertext) + +ASN1_SEQUENCE(SM9Signature) = { + ASN1_SIMPLE(SM9Signature, h, BIGNUM), + ASN1_SIMPLE(SM9Signature, pointS, ASN1_OCTET_STRING) +} ASN1_SEQUENCE_END(SM9Signature) +IMPLEMENT_ASN1_FUNCTIONS(SM9Signature) +IMPLEMENT_ASN1_DUP_FUNCTION(SM9Signature) + diff --git a/crypto/sm9/sm9_enc.c b/crypto/sm9/sm9_enc.c new file mode 100644 index 00000000..21bf14c3 --- /dev/null +++ b/crypto/sm9/sm9_enc.c @@ -0,0 +1,1112 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sm9_lcl.h" + +/* + * the encoded length of a point over E/F_p^k, k = 1, 2, 12 or others + * the encoding method can be DER or canonical + * the output is the about (2 * p * k) with some extra encoding bytes + */ +static int SM9PublicParameters_get_point_size(SM9PublicParameters *mpk, + size_t *outlen) +{ + size_t size; + int nbytes; + BN_ULONG k; + + if (!mpk || !mpk->p || !mpk->k || !outlen) { + SM9err(SM9_F_SM9PUBLICPARAMETERS_GET_POINT_SIZE, + ERR_R_MALLOC_FAILURE); + return 0; + } + + if ((nbytes = BN_num_bytes(mpk->p)) <= 0) { + SM9err(SM9_F_SM9PUBLICPARAMETERS_GET_POINT_SIZE, + SM9_R_INVALID_PARAMETER); + return 0; + } + + k = BN_get_word(mpk->k); + if (k <= 0 || k > 12) { + SM9err(SM9_F_SM9PUBLICPARAMETERS_GET_POINT_SIZE, + SM9_R_INVALID_PARAMETER); + return 0; + } + + /* major length is from x, y coordintates over F_p^k */ + size = 2 * nbytes * k; + + /* extra length of TLV encoding + * hope 16-byte for every field element encoding is enough + */ + size += 16 * (k + 1); + + *outlen = size; + return 1; +} + +int SM9_wrap_key(SM9PublicParameters *mpk, size_t keylen, + unsigned char *outkey, unsigned char *outcipher, size_t *outcipherlen, + const char *id, size_t idlen) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_POINT *Ppub = NULL; + BN_GFP2 *w = NULL; + unsigned char *buf = NULL; + BIGNUM *h; + BIGNUM *r; + unsigned char *pbuf; + const EVP_MD *md; + int point_form = POINT_CONVERSION_UNCOMPRESSED; + size_t size; + size_t buflen; + size_t outlen; + size_t wlen; + KDF_FUNC kdf_func; + + if (!mpk || !outkey || !outcipherlen || !id) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (keylen <= 0 || keylen > 4096) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_INVALID_KEY_LENGTH); + return 0; + } + if (idlen <= 0 || idlen > SM9_MAX_ID_LENGTH || strlen(id) != idlen) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_INVALID_ID); + return 0; + } + + /* + * get outlen + * outcipher length is encoded point on curve E/F_p^k + */ + if (!SM9PublicParameters_get_point_size(mpk, &outlen)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_SM9_LIB); + return 0; + } + if (!outcipher) { + *outcipherlen = outlen; + return 1; + } + if (*outcipherlen < outlen) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, + mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, + mpk->order, mpk->cofactor, bn_ctx))) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + point = EC_POINT_new(group); + Ppub = EC_POINT_new(group); + w = BN_GFP2_new(); + h = BN_CTX_get(bn_ctx); + r = BN_CTX_get(bn_ctx); + + if (!point || !Ppub || !w || !h || !r) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* get md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* h = H1(ID||hid) in range [0, mpk->order] */ + if (!SM9_hash1(md, &h, id, idlen, SM9_HID, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_HASH_FAILURE); + goto end; + } + + /* point = mpk->pointP1 * h */ + if (!EC_POINT_mul(group, point, h, NULL, NULL, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* Ppub = mpk->pointPpub */ + if (!EC_POINT_oct2point(group, Ppub, + mpk->pointPpub->data, mpk->pointPpub->length, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* point = point + Ppub = P1 * H1(ID||hid) + Ppub*/ + if (!EC_POINT_add(group, point, point, Ppub, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* rand r in (0, mpk->order) */ + do { + if (!BN_rand_range(r, mpk->order)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(r)); + + /* point = point * r = (P1 * H(ID||hid) + Ppub) * r */ + if (!EC_POINT_mul(group, point, NULL, point, r, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* output outcipher = point */ + if (!(outlen = EC_POINT_point2oct(group, point, point_form, + outcipher, outlen, bn_ctx))) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_EC_LIB); + goto end; + } + *outcipherlen = outlen; + + /* get w = mpk->g2 = e(Ppub, P2) in F_p^2 */ + if (!BN_bn2gfp2(mpk->g2, w, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_BN_LIB); + goto end; + } + + /* w = w^r in F_p^2 */ + if (!BN_GFP2_exp(w, w, r, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_BN_LIB); + goto end; + } + + /* get wlen */ + if (!BN_GFP2_canonical(w, NULL, &wlen, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_BN_LIB); + goto end; + } + + /* buflen = outlen + wlen + idlen + * buf is used for KDF to generate the output key + */ + buflen = outlen + wlen + idlen; + + /* malloc buf */ + if (!(buf = OPENSSL_malloc(buflen))) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* copy outcipher to buf */ + memcpy(buf, outcipher, outlen); + + /* canonical w to buf */ + pbuf = buf + outlen; + size = wlen; + if (!BN_GFP2_canonical(w, pbuf, &size, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_WRAP_KEY, ERR_R_BN_LIB); + goto end; + } + pbuf += size; + + /* copy id to buf */ + memcpy(pbuf, id, idlen); + + /* output key = KDF(C||w||ID), |key| = keylen */ + if (!(kdf_func = KDF_get_x9_63(md))) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_INVALID_MD); + goto end; + } + size = keylen; + if (!kdf_func(buf, buflen, outkey, &size)) { + SM9err(SM9_F_SM9_WRAP_KEY, SM9_R_KDF_FAILURE); + goto end; + } + + ret = 1; + +end: + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + EC_POINT_free(Ppub); + BN_GFP2_free(w); + OPENSSL_free(buf); + return ret; +} + +int SM9_unwrap_key(SM9PublicParameters *mpk, size_t keylen, + const unsigned char *incipher, size_t incipherlen, + unsigned char *outkey, + const char *id, size_t idlen, SM9PrivateKey *sk) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_POINT *point1 = NULL; + BN_GFP2 *w = NULL; + unsigned char *buf = NULL; + unsigned char *pbuf; + size_t buflen, wlen; + const EVP_MD *md; + KDF_FUNC kdf_func; + int i; + size_t outlen; + + if (!mpk || !incipher || !outkey || !id || !sk) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (keylen <= 0 || keylen >= 1024) { + SM9err(SM9_F_SM9_UNWRAP_KEY, SM9_R_INVALID_PARAMETER); + return 0; + } + if (id <= 0 || idlen > SM9_MAX_ID_LENGTH || strlen(id) != idlen) { + SM9err(SM9_F_SM9_UNWRAP_KEY, SM9_R_INVALID_PARAMETER); + return 0; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, + mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, + mpk->order, mpk->cofactor, bn_ctx))) { + SM9err(SM9_F_SM9_UNWRAP_KEY, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + SM9err(SM9_F_SM9_UNWRAP_KEY, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* malloc */ + point = EC_POINT_new(group); + point1 = EC_POINT_new(group); + w = BN_GFP2_new(); + + if (!point || !point1 || !w) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* point decoded from incipher in curve */ + if (!EC_POINT_oct2point(group, point, incipher, incipherlen, bn_ctx)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* point1 decoded from sk->privatePoint */ + if (!EC_POINT_oct2point(group, point1, + sk->privatePoint->data, sk->privatePoint->length, bn_ctx)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* w = e(point, sk->privatePoint) in F_p^2 */ + if (!EC_type1curve_tate(group, w, point, point1, bn_ctx)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* wbuflen is canonical w length */ + if (!BN_GFP2_canonical(w, NULL, &wlen, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* buflen = incipherlen + wlen + idlen */ + buflen = incipherlen + wlen + idlen; + + /* buf = malloc(buflen) */ + if (!(buf = OPENSSL_malloc(buflen))) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + pbuf = buf; + + /* copy incipher to buf */ + memcpy(pbuf, incipher, incipherlen); + pbuf += incipherlen; + + /* canonical w to buf */ + if (!BN_GFP2_canonical(w, pbuf, &wlen, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + pbuf += wlen; + + /* copy id to buf */ + memcpy(pbuf, id, idlen); + + /* outkey = KDF(buf, outkeylen) */ + if (!(kdf_func = KDF_get_x9_63(md))) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + outlen = keylen; + if (!kdf_func(buf, buflen, outkey, &outlen)) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + /* is outkey is all zero, return failed */ + for (i = 0; (i < keylen) && (outkey[i] == 0); i++) { + } + if (i == keylen) { + SM9err(SM9_F_SM9_UNWRAP_KEY, ERR_R_EC_LIB); + goto end; + } + + ret = 1; + +end: + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + EC_POINT_free(point1); + BN_GFP2_free(w); + OPENSSL_free(buf); + return ret; +} + +static int SM9EncParameters_get_key_length(const SM9EncParameters *encparams, + size_t inlen, size_t *enckeylen, size_t *mackeylen) +{ + int len; + + if (encparams->enc_cipher) { + len = EVP_CIPHER_key_length(encparams->enc_cipher); + if (len <= 0 || len > 256/8) { + SM9err(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH, + SM9_R_INVALID_ENCPARAMETERS); + return 0; + } + *enckeylen = (size_t)len; + + } else { + *enckeylen = inlen; + } + + if (encparams->hmac_md && + !encparams->cmac_cipher && !encparams->cbcmac_cipher) { + len = EVP_MD_size(encparams->hmac_md); + if (len <= 0 || len > EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH, + SM9_R_INVALID_ENCPARAMETERS); + return 0; + } + *mackeylen = (size_t)len; + } else if (encparams->cmac_cipher && + !encparams->hmac_md && !encparams->cbcmac_cipher) { + len = EVP_CIPHER_key_length(encparams->cmac_cipher); + if (len <= 0 || len > 256/8) { + SM9err(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH, + SM9_R_INVALID_ENCPARAMETERS); + return 0; + } + *enckeylen = (size_t)len; + } else if (encparams->cbcmac_cipher && + !encparams->hmac_md && !encparams->cmac_cipher) { + len = EVP_CIPHER_key_length(encparams->cbcmac_cipher); + if (len <= 0 || len > 256/8) { + SM9err(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH, + SM9_R_INVALID_ENCPARAMETERS); + return 0; + } + *enckeylen = (size_t)len; + } else { + SM9err(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH, + SM9_R_INVALID_ENCPARAMETERS); + return 0; + } + + return 1; +} + +static int SM9EncParameters_encrypt(const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const unsigned char *key) +{ + int ret = 0; + EVP_CIPHER_CTX *cipher_ctx = NULL; + size_t size; + + if (!encparams || !in || !outlen || !key) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (inlen <= 0 || inlen > 1024) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, SM9_R_INVALID_INPUT); + return 0; + } + + if (encparams->enc_cipher) { + size = inlen + 16 * 3; + } else { + size = inlen; + } + + if (!out) { + *outlen = size; + return 1; + } + if (*outlen < size) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + if (encparams->enc_cipher) { + unsigned char *iv; + unsigned char *p; + int ivlen, len; + + /* output iv */ + iv = out; + ivlen = EVP_CIPHER_iv_length(encparams->enc_cipher); + RAND_bytes(iv, ivlen); + + /* encrypt */ + if (!(cipher_ctx = EVP_CIPHER_CTX_new())) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EVP_EncryptInit(cipher_ctx, encparams->enc_cipher, key, iv)) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, ERR_R_EVP_LIB); + goto end; + } + + p = out + ivlen; + + if (!EVP_EncryptUpdate(cipher_ctx, p, &len, in, inlen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, ERR_R_EVP_LIB); + goto end; + } + p += len; + + if (!EVP_EncryptFinal(cipher_ctx, p, &len)) { + SM9err(SM9_F_SM9ENCPARAMETERS_ENCRYPT, ERR_R_EVP_LIB); + goto end; + } + p += len; + + size = p - out; + + } else { + size_t i; + + for (i = 0; i < inlen; i++) { + out[i] = key[i] ^ in[i]; + } + + size = inlen; + } + + *outlen = size; + ret = 1; + +end: + EVP_CIPHER_CTX_free(cipher_ctx); + return ret; +} + +static int SM9EncParameters_decrypt(const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const unsigned char *key) +{ + int ret = 0; + EVP_CIPHER_CTX *cipher_ctx = NULL; + size_t size; + + if (!encparams || !in || !outlen || !key) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (inlen <= 0 || inlen > 1024) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, SM9_R_INVALID_INPUT); + return 0; + } + + size = inlen; + if (!out) { + *outlen = size; + return 1; + } + if (*outlen < size) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + if (encparams->enc_cipher) { + const unsigned char *iv; + unsigned char *p; + int ivlen, len; + + /* output iv */ + iv = in; + ivlen = EVP_CIPHER_iv_length(encparams->enc_cipher); + if (inlen <= ivlen) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, SM9_R_INVALID_CIPHERTEXT); + goto end; + } + + /* encrypt */ + if (!(cipher_ctx = EVP_CIPHER_CTX_new())) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EVP_DecryptInit(cipher_ctx, encparams->enc_cipher, key, iv)) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, ERR_R_EVP_LIB); + goto end; + } + + in = in + ivlen; + inlen = inlen - ivlen; + p = out; + + if (!EVP_DecryptUpdate(cipher_ctx, p, &len, in, inlen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, ERR_R_EVP_LIB); + goto end; + } + p += len; + + if (!EVP_DecryptFinal(cipher_ctx, p, &len)) { + SM9err(SM9_F_SM9ENCPARAMETERS_DECRYPT, ERR_R_EVP_LIB); + goto end; + } + p += len; + + size = p - out; + + } else { + size_t i; + for (i = 0; i < inlen; i++) { + out[i] = key[i] ^ in[i]; + } + size = inlen; + } + + *outlen = size; + ret = 1; + +end: + EVP_CIPHER_CTX_free(cipher_ctx); + return ret; +} + +/* + * don't need input keylen because keylen can be get from encparams, + * this makes the API simpler and with less error + */ +static int SM9EncParameters_generate_mac(const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *mac, size_t *maclen, + const unsigned char *key) +{ + int ret = 0; + HMAC_CTX *hmac_ctx = NULL; + CMAC_CTX *cmac_ctx = NULL; + CMAC_CTX *cbcmac_ctx = NULL; + size_t size; + size_t mackeylen; + unsigned int len; + + if (!encparams || !in || !maclen || !key) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, + ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!mac) { + *maclen = EVP_MAX_MD_SIZE; + return 1; + } + /* require outbuf enough to hold max HMAC tag */ + if (*maclen < EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, + SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + if (!SM9EncParameters_get_key_length(encparams, inlen, &size, &mackeylen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, ERR_R_SM9_LIB); + goto end; + } + + if (encparams->hmac_md && + !encparams->cmac_cipher && !encparams->cbcmac_cipher) { + if (!(hmac_ctx = HMAC_CTX_new())) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!HMAC_Init_ex(hmac_ctx, key, mackeylen, encparams->hmac_md, NULL)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!HMAC_Update(hmac_ctx, in, inlen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!HMAC_Final(hmac_ctx, mac, &len)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + *maclen = (size_t)len; + + } else if (encparams->cmac_cipher && + !encparams->hmac_md && !encparams->cbcmac_cipher) { + if (!(cmac_ctx = CMAC_CTX_new())) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!CMAC_Init(cmac_ctx, key, mackeylen, encparams->cmac_cipher, NULL)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!CMAC_Update(cmac_ctx, in, inlen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!CMAC_Final(cmac_ctx, mac, &size)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + *maclen = size; + + } else if (encparams->cbcmac_cipher && + !encparams->hmac_md && !encparams->cmac_cipher) { + if (!(cbcmac_ctx = CMAC_CTX_new())) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!CMAC_Init(cbcmac_ctx, key, mackeylen, encparams->cbcmac_cipher, NULL)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!CMAC_Update(cbcmac_ctx, in, inlen)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + if (!CMAC_Final(cbcmac_ctx, mac, &size)) { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_GENERATE_MAC_FAILURE); + goto end; + } + *maclen = size; + + } else { + SM9err(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC, SM9_R_INVALID_PARAMETER); + goto end; + } + + ret = 1; +end: + HMAC_CTX_free(hmac_ctx); + CMAC_CTX_free(cmac_ctx); + CMAC_CTX_free(cbcmac_ctx); + return ret; +} + +SM9Ciphertext *SM9_do_encrypt(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen) +{ + int e = 1; + SM9Ciphertext *ret = NULL; + unsigned char *key = NULL; + unsigned char *enckey, *mackey; + size_t keylen, enckeylen, mackeylen; + size_t size; + + if (!mpk || !encparams || !in || !id) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (idlen <= 0 || idlen > SM9_MAX_ID_LENGTH || strlen(id) != idlen) { + SM9err(SM9_F_SM9_DO_ENCRYPT, SM9_R_INVALID_ID); + return NULL; + } + if (inlen <= 0 || inlen > 1024) { + SM9err(SM9_F_SM9_DO_ENCRYPT, SM9_R_INVALID_INPUT); + return NULL; + } + if (strlen(id) != idlen || idlen > SM9_MAX_ID_LENGTH) { + SM9err(SM9_F_SM9_DO_ENCRYPT, SM9_R_INVALID_ID); + return NULL; + } + + if (!(ret = SM9Ciphertext_new())) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* keylen = enckeylen + mackeylen */ + if (!SM9EncParameters_get_key_length(encparams, inlen, &enckeylen, &mackeylen)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + keylen = enckeylen + mackeylen; + + /* prepare key buffer */ + if (!(key = OPENSSL_malloc(keylen))) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* (enckey, mackey) = wrap_key() */ + if (!SM9_wrap_key(mpk, keylen, NULL, NULL, &size, id, idlen)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(ret->pointC1, NULL, size)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!SM9_wrap_key(mpk, keylen, key, ret->pointC1->data, &size, id, idlen)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + enckey = key; + mackey = key + enckeylen; + + /* ret->c2 = encrypt(in, enckey) */ + if (!SM9EncParameters_encrypt(encparams, in, inlen, NULL, &size, enckey)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(ret->c2, NULL, size)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!SM9EncParameters_encrypt(encparams, in, inlen, ret->c2->data, &size, enckey)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + + /* ret->c3 = mac(ret->c2, mackey) */ + if (!SM9EncParameters_generate_mac(encparams, + ret->c2->data, ret->c2->length, NULL, &size, mackey)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(ret->c3, NULL, size)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!SM9EncParameters_generate_mac(encparams, + ret->c2->data, ret->c2->length, ret->c3->data, &size, mackey)) { + SM9err(SM9_F_SM9_DO_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + + e = 0; + +end: + if (e && ret) { + SM9Ciphertext_free(ret); + ret = NULL; + } + OPENSSL_cleanse(key, keylen); + OPENSSL_free(key); + return ret; +} + +#define SM9_MAX_CIPHERTEXT_LENGTH 1024 +static int SM9Ciphertext_check(const SM9Ciphertext *in) +{ + if (!in->pointC1 || !in->c2 || !in->c3) { + SM9err(SM9_F_SM9CIPHERTEXT_CHECK, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + if (!in->pointC1->data || in->pointC1->length <= 0) { + SM9err(SM9_F_SM9CIPHERTEXT_CHECK, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + if (!in->c2 || in->c2->length <= 0) { + SM9err(SM9_F_SM9CIPHERTEXT_CHECK, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + if (!in->c3 || in->c3->length <= 0) { + SM9err(SM9_F_SM9CIPHERTEXT_CHECK, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + if (in->c2->length > SM9_MAX_CIPHERTEXT_LENGTH) { + SM9err(SM9_F_SM9CIPHERTEXT_CHECK, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + return 1; +} + +int SM9_do_decrypt(SM9PublicParameters *mpk, const SM9EncParameters *encparams, + const SM9Ciphertext *in, unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, const char *id, size_t idlen) +{ + int ret = 0; + unsigned char *key = NULL; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned char *enckey, *mackey; + size_t keylen, enckeylen, mackeylen; + size_t size; + + if (!mpk || !encparams || !in || !outlen || !sk) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!SM9Ciphertext_check(in)) { + SM9err(SM9_F_SM9_DO_DECRYPT, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + + if (!out) { + *outlen = in->c2->length; + return 1; + } + if (*outlen < in->c2->length) { + SM9err(SM9_F_SM9_DO_DECRYPT, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + /* keylen = enckeylen + mackeylen */ + if (!SM9EncParameters_get_key_length(encparams, in->c2->length, + &enckeylen, &mackeylen)) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + keylen = enckeylen + mackeylen; + + /* prepare key buffer */ + if (!(key = OPENSSL_malloc(keylen))) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* (enckey, mackey) = wrap_key() */ + if (!SM9_unwrap_key(mpk, keylen, + in->pointC1->data, in->pointC1->length, key, id, idlen, sk)) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + enckey = key; + mackey = key + enckeylen; + + /* check in->c3 == mac(ret->c2, mackey) */ + if (!SM9EncParameters_generate_mac(encparams, + in->c2->data, in->c2->length, mac, &size, mackey)) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + if (in->c3->length != size || memcmp(in->c3->data, mac, size) != 0) { + SM9err(SM9_F_SM9_DO_DECRYPT, SM9_R_INVALID_CIPHERTEXT); + goto end; + } + + /* ret->c2 = decrypt(in, enckey) */ + if (!SM9EncParameters_decrypt(encparams, in->c2->data, in->c2->length, + out, &size, enckey)) { + SM9err(SM9_F_SM9_DO_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + *outlen = size; + + ret = 1; + +end: + OPENSSL_cleanse(key, keylen); + OPENSSL_free(key); + return ret; +} + +static int SM9Ciphertext_size(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, size_t inlen, size_t *outlen) +{ + if (!outlen) { + return 0; + } + *outlen = inlen + 4096; +} + +int SM9_encrypt(SM9PublicParameters *mpk, const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen) +{ + int ret = 0; + SM9Ciphertext *c = NULL; + + if (!mpk || !encparams || !in || !outlen || !id) { + SM9err(SM9_F_SM9_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!(c = SM9_do_encrypt(mpk, encparams, in, inlen, id, idlen))) { + SM9err(SM9_F_SM9_ENCRYPT, ERR_R_SM9_LIB); + goto end; + } + +end: + return 0; +} + +int SM9_decrypt(SM9PublicParameters *mpk, const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, const char *id, size_t idlen) +{ + int ret = 0; + SM9Ciphertext *c = NULL; + const unsigned char *p; + + if (!mpk || !encparams || !in || !outlen || !sk) { + SM9err(SM9_F_SM9_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (inlen <= 0 || inlen > SM9_MAX_CIPHERTEXT_LENGTH) { + SM9err(SM9_F_SM9_DECRYPT, SM9_R_INVALID_CIPHERTEXT); + return 0; + } + if (idlen <= 0 || idlen > SM9_MAX_ID_LENGTH || strlen(id) != idlen) { + SM9err(SM9_F_SM9_DECRYPT, SM9_R_INVALID_ID_LENGTH); + return 0; + } + + if (!out) { + *outlen = inlen; + return 1; + } + if (*outlen < inlen) { + SM9err(SM9_F_SM9_DECRYPT, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + p = ∈ + if (!(c = d2i_SM9Ciphertext(NULL, &p, inlen))) { + SM9err(SM9_F_SM9_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + + if (!(SM9_do_decrypt(mpk, encparams, c, out, outlen, sk, id, idlen))) { + SM9err(SM9_F_SM9_DECRYPT, ERR_R_SM9_LIB); + goto end; + } + + ret = 1; +end: + SM9Ciphertext_free(c); + return ret; +} + +static int SM9EncParameters_init_with_recommended(SM9EncParameters *encparams) +{ + if (!encparams) { + return 0; + } + memset(encparams, 0, sizeof(*encparams)); + encparams->kdf_md = EVP_sm3(); + encparams->enc_cipher = EVP_sms4_cbc(); + encparams->cmac_cipher = NULL; + encparams->hmac_md = EVP_sm3(); + return 1; +} + +int SM9_encrypt_with_recommended(SM9PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen) +{ + SM9EncParameters encparams; + SM9EncParameters_init_with_recommended(&encparams); + return SM9_encrypt(mpk, &encparams, in, inlen, out, outlen, id, idlen); +} + +int SM9_decrypt_with_recommended(SM9PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, const char *id, size_t idlen) +{ + SM9EncParameters encparams; + SM9EncParameters_init_with_recommended(&encparams); + return SM9_decrypt(mpk, &encparams, in, inlen, out, outlen, sk, id, idlen); +} + diff --git a/crypto/sm9/sm9_err.c b/crypto/sm9/sm9_err.c new file mode 100644 index 00000000..92ffd5c4 --- /dev/null +++ b/crypto/sm9/sm9_err.c @@ -0,0 +1,85 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_SM9,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_SM9,0,reason) + +static ERR_STRING_DATA SM9_str_functs[] = { + {ERR_FUNC(SM9_F_SM9CIPHERTEXT_CHECK), "SM9Ciphertext_check"}, + {ERR_FUNC(SM9_F_SM9ENCPARAMETERS_DECRYPT), "SM9EncParameters_decrypt"}, + {ERR_FUNC(SM9_F_SM9ENCPARAMETERS_ENCRYPT), "SM9EncParameters_encrypt"}, + {ERR_FUNC(SM9_F_SM9ENCPARAMETERS_GENERATE_MAC), + "SM9EncParameters_generate_mac"}, + {ERR_FUNC(SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH), + "SM9EncParameters_get_key_length"}, + {ERR_FUNC(SM9_F_SM9PUBLICPARAMETERS_GET_POINT_SIZE), + "SM9PublicParameters_get_point_size"}, + {ERR_FUNC(SM9_F_SM9_DECRYPT), "SM9_decrypt"}, + {ERR_FUNC(SM9_F_SM9_DO_DECRYPT), "SM9_do_decrypt"}, + {ERR_FUNC(SM9_F_SM9_DO_ENCRYPT), "SM9_do_encrypt"}, + {ERR_FUNC(SM9_F_SM9_DO_SIGN), "SM9_do_sign"}, + {ERR_FUNC(SM9_F_SM9_DO_SIGN_TYPE1CURVE), "SM9_do_sign_type1curve"}, + {ERR_FUNC(SM9_F_SM9_DO_VERIFY), "SM9_do_verify"}, + {ERR_FUNC(SM9_F_SM9_DO_VERIFY_TYPE1CURVE), "SM9_do_verify_type1curve"}, + {ERR_FUNC(SM9_F_SM9_ENCRYPT), "SM9_encrypt"}, + {ERR_FUNC(SM9_F_SM9_EXTRACT_PRIVATE_KEY), "SM9_extract_private_key"}, + {ERR_FUNC(SM9_F_SM9_SETUP_TYPE1CURVE), "SM9_setup_type1curve"}, + {ERR_FUNC(SM9_F_SM9_SIGN), "SM9_sign"}, + {ERR_FUNC(SM9_F_SM9_UNWRAP_KEY), "SM9_unwrap_key"}, + {ERR_FUNC(SM9_F_SM9_VERIFY), "SM9_verify"}, + {ERR_FUNC(SM9_F_SM9_WRAP_KEY), "SM9_wrap_key"}, + {0, NULL} +}; + +static ERR_STRING_DATA SM9_str_reasons[] = { + {ERR_REASON(SM9_R_BUFFER_TOO_SMALL), "buffer too small"}, + {ERR_REASON(SM9_R_COMPUTE_PAIRING_FAILURE), "compute pairing failure"}, + {ERR_REASON(SM9_R_GENERATE_MAC_FAILURE), "generate mac failure"}, + {ERR_REASON(SM9_R_HASH_FAILURE), "hash failure"}, + {ERR_REASON(SM9_R_INVALID_CIPHERTEXT), "invalid ciphertext"}, + {ERR_REASON(SM9_R_INVALID_CURVE), "invalid curve"}, + {ERR_REASON(SM9_R_INVALID_DIGEST), "invalid digest"}, + {ERR_REASON(SM9_R_INVALID_DIGEST_LENGTH), "invalid digest length"}, + {ERR_REASON(SM9_R_INVALID_ENCPARAMETERS), "invalid encparameters"}, + {ERR_REASON(SM9_R_INVALID_ID), "invalid id"}, + {ERR_REASON(SM9_R_INVALID_ID_LENGTH), "invalid id length"}, + {ERR_REASON(SM9_R_INVALID_INPUT), "invalid input"}, + {ERR_REASON(SM9_R_INVALID_KEY_LENGTH), "invalid key length"}, + {ERR_REASON(SM9_R_INVALID_MD), "invalid md"}, + {ERR_REASON(SM9_R_INVALID_PARAMETER), "invalid parameter"}, + {ERR_REASON(SM9_R_INVALID_SIGNATURE), "invalid signature"}, + {ERR_REASON(SM9_R_INVALID_TYPE1CURVE), "invalid type1curve"}, + {ERR_REASON(SM9_R_KDF_FAILURE), "kdf failure"}, + {ERR_REASON(SM9_R_NOT_NAMED_CURVE), "not named curve"}, + {ERR_REASON(SM9_R_PARSE_PAIRING), "parse pairing"}, + {ERR_REASON(SM9_R_ZERO_ID), "zero id"}, + {0, NULL} +}; + +#endif + +int ERR_load_SM9_strings(void) +{ +#ifndef OPENSSL_NO_ERR + + if (ERR_func_error_string(SM9_str_functs[0].error) == NULL) { + ERR_load_strings(0, SM9_str_functs); + ERR_load_strings(0, SM9_str_reasons); + } +#endif + return 1; +} diff --git a/crypto/sm9/sm9_kap.c b/crypto/sm9/sm9_kap.c new file mode 100644 index 00000000..506b9e80 --- /dev/null +++ b/crypto/sm9/sm9_kap.c @@ -0,0 +1,53 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include "sm9_lcl.h" + diff --git a/crypto/sm9/sm9_keygen.c b/crypto/sm9/sm9_keygen.c new file mode 100644 index 00000000..bf8d0288 --- /dev/null +++ b/crypto/sm9/sm9_keygen.c @@ -0,0 +1,173 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include "sm9_lcl.h" + + +SM9PrivateKey *SM9_extract_private_key(SM9PublicParameters *mpk, + SM9MasterSecret *msk, const char *id, size_t idlen) +{ + int e = 1; + SM9PrivateKey *ret = NULL; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + BIGNUM *h; + const EVP_MD *md; + int point_form = POINT_CONVERSION_UNCOMPRESSED; + size_t size; + + if (!mpk || !msk || !id) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (strlen(id) != idlen || idlen <= 0 || idlen > SM9_MAX_ID_LENGTH) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, + SM9_R_INVALID_ID); + return NULL; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, + ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, + mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, + mpk->order, mpk->cofactor, bn_ctx))) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* malloc */ + ret = SM9PrivateKey_new(); + point = EC_POINT_new(group); + h = BN_CTX_get(bn_ctx); + + if (!ret || !point || !h) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, SM9_R_INVALID_MD); + goto end; + } + + /* h = H1(ID||HID) in [0, mpk->order] */ + if (!SM9_hash1(md, &h, id, idlen, SM9_HID, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_SM9_LIB); + goto end; + } + + /* h = h + msk->masterSecret (mod mpk->order) */ + if (!BN_mod_add(h, h, msk->masterSecret, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + + /* if h is zero, return failed */ + if (BN_is_zero(h)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, SM9_R_ZERO_ID); + goto end; + } + + /* h = msk->masterSecret * h^-1 (mod mpk->order) */ + if (!BN_mod_inverse(h, h, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_mul(h, msk->masterSecret, h, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_BN_LIB); + goto end; + } + + /* sk->privatePoint = mpk->pointP1 * h */ + if (!EC_POINT_mul(group, point, h, NULL, NULL, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + if (!(size = EC_POINT_point2oct(group, point, point_form, + NULL, 0, bn_ctx))) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(ret->privatePoint, NULL, size)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EC_POINT_point2oct(group, point, point_form, + ret->privatePoint->data, ret->privatePoint->length, bn_ctx)) { + SM9err(SM9_F_SM9_EXTRACT_PRIVATE_KEY, ERR_R_EC_LIB); + goto end; + } + + e = 0; + +end: + if (e && ret) { + SM9PrivateKey_free(ret); + ret = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + return NULL; +} diff --git a/crypto/sm9/sm9_lcl.h b/crypto/sm9/sm9_lcl.h new file mode 100644 index 00000000..fa313620 --- /dev/null +++ b/crypto/sm9/sm9_lcl.h @@ -0,0 +1,129 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ + +#ifndef HEADER_SM9_LCL_H +#define HEADER_SM9_LCL_H + +#include +#include + +/* Curve ID */ +#define SM9_CID_TYPE0CURVE 0x10 +#define SM9_CID_TYPE1CURVE 0x11 +#define SM9_CID_TYPE2CURVE 0x12 + +/* Pairing ID */ +#define SM9_EID_TATE 0x01 +#define SM9_EID_WEIL 0x02 +#define SM9_EID_ATE 0x03 +#define SM9_EID_RATE 0x04 + +#define SM9_MAX_ID_LENGTH 127 + +/* not clear what it is */ +#define SM9_HID 0xc9 + +#ifdef __cplusplus +extern "C" { +#endif + +struct SM9PublicParameters_st { + ASN1_OBJECT *curve; + BIGNUM *p; + BIGNUM *a; + BIGNUM *b; + BIGNUM *beta; + BIGNUM *order; + BIGNUM *cofactor; + BIGNUM *k; + ASN1_OCTET_STRING *pointP1; + ASN1_OCTET_STRING *pointP2; + ASN1_OBJECT *pairing; + ASN1_OCTET_STRING *pointPpub; + BIGNUM *g1; /* g1 = e(P1, Ppub) */ + BIGNUM *g2; /* g2 = e(Ppub, P2) */ + ASN1_OBJECT *hashfcn; +}; + +struct SM9MasterSecret_st { + BIGNUM *masterSecret; +}; + +struct SM9PrivateKey_st { + ASN1_OCTET_STRING *privatePoint; +}; + +struct SM9Ciphertext_st { + ASN1_OCTET_STRING *pointC1; + ASN1_OCTET_STRING *c2; + ASN1_OCTET_STRING *c3; +}; + +struct SM9Signature_st { + BIGNUM *h; + ASN1_OCTET_STRING *pointS; +}; + + +int SM9_hash1(const EVP_MD *md, BIGNUM **r, + const char *id, size_t idlen, unsigned char hid, + const BIGNUM *range, BN_CTX *ctx); + +int SM9_hash2(const EVP_MD *md, BIGNUM **r, + const unsigned char *data, size_t datalen, + const unsigned char *elem, size_t elemlen, + const BIGNUM *range, BN_CTX *ctx); + +EC_GROUP *EC_GROUP_new_sm9s256t1(void); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/crypto/sm9/sm9_lib.c b/crypto/sm9/sm9_lib.c new file mode 100644 index 00000000..2bd92816 --- /dev/null +++ b/crypto/sm9/sm9_lib.c @@ -0,0 +1,98 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include "sm9_lcl.h" + +int SM9_hash1(const EVP_MD *md, BIGNUM **r, + const char *id, size_t idlen, + unsigned char hid, + const BIGNUM *range, + BN_CTX *ctx) +{ + unsigned char *buf; + + if (!(buf = OPENSSL_malloc(idlen + 1))) { + return 0; + } + memcpy(buf, id, idlen); + buf[idlen] = hid; + + if (!BN_hash_to_range(md, r, buf, idlen + 1, range, ctx)) { + OPENSSL_free(buf); + return 0; + } + + OPENSSL_free(buf); + return 1; +} + +int SM9_hash2(const EVP_MD *md, BIGNUM **r, + const unsigned char *data, size_t datalen, + const unsigned char *elem, size_t elemlen, + const BIGNUM *range, BN_CTX *ctx) +{ + unsigned char *buf; + + if (!(buf = OPENSSL_malloc(datalen + elemlen))) { + return 0; + } + memcpy(buf, data, datalen); + memcpy(buf + datalen, elem, elemlen); + + if (!BN_hash_to_range(md, r, buf, datalen + elemlen, range, ctx)) { + OPENSSL_free(buf); + return 0; + } + + OPENSSL_free(buf); + return 1; +} + diff --git a/crypto/sm9/sm9_params.c b/crypto/sm9/sm9_params.c new file mode 100644 index 00000000..d0067f2c --- /dev/null +++ b/crypto/sm9/sm9_params.c @@ -0,0 +1,181 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include + + +#define P_HEX \ + "ab64be0955a39254a6cfe231531c02ebc0cd4c307800c7eb49fabcc179174e04" \ + "00365f7280d166bf67839bba4047bab1212f2966d3045dcfc08d83d57fb7d01b" \ + "6f958e077caeba969057287a8ea75c93660747c68c32af9c874bfd87d1a40c9a" \ + "a709813930f3e7d7d794874146eceb73a14cfc41cfad0007fc30ead26f938349" \ + "a017115a506c49dfb78002ccffaed045b39bc8970756c275d484f60dc7ba609f" \ + "8dfe7142f8dfac81cc53a6bd67e1dcc18f35aad88a94ee40dd90934a282203cb" +#define A_HEX "0" +#define B_HEX "1" +#define X_HEX \ + "6613bde4d70b02a29a1700d2063420e408b0c23c85fdfca2b37df38b872492f1" \ + "91dda03d4c520be9dced93d8678c5a898a9e81ddddb6afc9fa882e808fb48e33" \ + "bd3e08756db0db2b271e82c48139d6b048edffd7736b0aca63f8733c2134ab7e" \ + "0b33f11a0e61b89bd7259b752b24ada949b958f95d2c914b34e29a6ee888acc6" \ + "04ab0d0818fc2ab09546db9eab4a452909ce88298abc644678f8b9ecbee7eb33" \ + "4ffe4c25a8d5fcd7dd4b74d0362033acacd3cd363f22ab2a76605fdc8868654b" +#define Y_HEX \ + "117ff162e1e4a92fc920677f84a2b9ab151f3545f5094f6471d8d02d47bd8b7e" \ + "b09e4ef771710be64809442ee66965406f6a55d317a8dde231d257f5fc2e84bf" \ + "99e3077e9f53cb49e8c6d792437cb1b525ea7e83594b2928e72db64349619fb4" \ + "7392759c9909f7ccd9d7d54b2605969ed59875a39a99e6914404d17d4f5a8ba2" \ + "d7486aa36ee235dcdc4385a292348c4de9373d4cae3fcb07297aef083dc04f10" \ + "d25efb6b60d116d0b95151a3ff96a2eaee556bbac0ad6b6633dfd1c1d5c896e2" +#define N_HEX \ + "ffffffffffffffffffffff000000000000000000000000000000000000000001" +#define H_HEX \ + "ab64be0955a39254a6cfe2dcb7da0c41645fa0d747e3a4a32406fe25d8b8254b" \ + "3876448d322bfa4378d90415feb23ba1e8c9cc086424cf2b4ec2279870cbb334" \ + "5bee74c90caa58c3e33158c07e69e9fe27963fa15966a0efa273d416f717fabf" \ + "b1bbfc12981da60b0c5dee32847f140d975cc7acd434919cd8d12452d543355e" \ + "22ecb2208972f6a9ee5772bd67e1dcc18f35aad88a94ee40dd90934a282203cc" + +static EC_GROUP *EC_GROUP_new_hexstrs(int is_prime_field, + const char *p_hex, const char *a_hex, const char *b_hex, + const char *x_hex, const char *y_hex, const char *n_hex, const char *h_hex) +{ + int ok = 0; + EC_GROUP *group = NULL; + BN_CTX *ctx = NULL; + BIGNUM *p = NULL; + BIGNUM *a = NULL; + BIGNUM *b = NULL; + BIGNUM *x = NULL; + BIGNUM *y = NULL; + BIGNUM *n = NULL; + BIGNUM *h = NULL; + EC_POINT *G = NULL; + point_conversion_form_t form = POINT_CONVERSION_COMPRESSED; + int flag = 0; + + if (!(ctx = BN_CTX_new())) { + ERR_print_errors_fp(stderr); + goto err; + } + + if (!BN_hex2bn(&p, p_hex) || + !BN_hex2bn(&a, a_hex) || + !BN_hex2bn(&b, b_hex) || + !BN_hex2bn(&x, x_hex) || + !BN_hex2bn(&y, y_hex) || + !BN_hex2bn(&n, n_hex) || + !BN_hex2bn(&h, h_hex)) { + ERR_print_errors_fp(stderr); + goto err; + } + + if (is_prime_field) { + if (!(group = EC_GROUP_new_curve_GFp(p, a, b, ctx))) { + ERR_print_errors_fp(stderr); + goto err; + } + if (!(G = EC_POINT_new(group))) { + ERR_print_errors_fp(stderr); + goto err; + } + if (!EC_POINT_set_affine_coordinates_GFp(group, G, x, y, ctx)) { + ERR_print_errors_fp(stderr); + goto err; + } + } else { + if (!(group = EC_GROUP_new_curve_GF2m(p, a, b, ctx))) { + goto err; + } + if (!(G = EC_POINT_new(group))) { + goto err; + } + if (!EC_POINT_set_affine_coordinates_GF2m(group, G, x, y, ctx)) { + goto err; + } + } + + if (!EC_GROUP_set_generator(group, G, n, h)) { + ERR_print_errors_fp(stderr); + goto err; + } + + EC_GROUP_set_asn1_flag(group, flag); + EC_GROUP_set_point_conversion_form(group, form); + + ok = 1; +err: + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + BN_free(x); + BN_free(y); + BN_free(n); + BN_free(h); + EC_POINT_free(G); + if (!ok && group) { + ERR_print_errors_fp(stderr); + EC_GROUP_free(group); + group = NULL; + } + + return group; +} + +EC_GROUP *EC_GROUP_new_sm9s256t1(void) +{ + return EC_GROUP_new_hexstrs(1, P_HEX, A_HEX, B_HEX, X_HEX, Y_HEX, N_HEX, H_HEX); +} + diff --git a/crypto/sm9/sm9_setup.c b/crypto/sm9/sm9_setup.c new file mode 100644 index 00000000..3bbf4067 --- /dev/null +++ b/crypto/sm9/sm9_setup.c @@ -0,0 +1,226 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include "sm9_lcl.h" + +int SM9_setup_type1curve(const EC_GROUP *group, const EVP_MD *md, + SM9PublicParameters **pmpk, SM9MasterSecret **pmsk) +{ + int ret = 0; + SM9PublicParameters *mpk = NULL; + SM9MasterSecret *msk = NULL; + BN_CTX *bn_ctx = NULL; + EC_POINT *point = NULL; + int point_form = POINT_CONVERSION_UNCOMPRESSED; + size_t size; + + if (!group || !pmpk || !pmsk) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + + mpk = SM9PublicParameters_new(); + msk = SM9MasterSecret_new(); + point = EC_POINT_new(group); + + if (!mpk || !msk || !point) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* set mpk->curve */ + OPENSSL_assert(mpk->curve); + ASN1_OBJECT_free(mpk->curve); + if (!(mpk->curve = OBJ_nid2obj(NID_type1curve))) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_NOT_NAMED_CURVE); + goto end; + } + + /* mpk->p = group->p + * mpk->a = group->a + * mpk->b = group->b + */ + if (!EC_GROUP_get_curve_GFp(group, mpk->p, mpk->a, mpk->b, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!BN_is_zero(mpk->a) || !BN_is_one(mpk->b)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* mpk->beta = 0 */ + if (!BN_zero(mpk->beta)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* mpk->order = group->order */ + if (!EC_GROUP_get_order(group, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* mpk->cofactor = group->cofactor */ + if (!EC_GROUP_get_cofactor(group, mpk->cofactor, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* mpk->k = 2 */ + if (!BN_set_word(mpk->k, 2)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* mpk->pointP1 = group->generator + * mpk->pointP2 = group->generator + */ + if (!(size = EC_POINT_point2oct(group, EC_GROUP_get0_generator(group), + point_form, NULL, 0, bn_ctx))) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(mpk->pointP1, NULL, size)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EC_POINT_point2oct(group, EC_GROUP_get0_generator(group), + point_form, mpk->pointP1->data, mpk->pointP1->length, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(mpk->pointP2, + mpk->pointP1->data, mpk->pointP1->length)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* mpk->pairing = "tate" */ + ASN1_OBJECT_free(mpk->pairing); + if (!(mpk->pairing = OBJ_nid2obj(NID_tate_pairing))) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_PARSE_PAIRING); + goto end; + } + + /* set mpk->hashfcn */ + OPENSSL_assert(mpk->hashfcn); + ASN1_OBJECT_free(mpk->hashfcn); + if (!(mpk->hashfcn = OBJ_nid2obj(EVP_MD_type(md)))) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, SM9_R_PARSE_PAIRING); + goto end; + } + + /* set mpk->g1 = e(P1, Ppub) */ + //TODO + + /* set mpk->g2 = e(Ppub, P2) */ + //TODO + + /* random msk->masterSecret in [2, mpk->order - 1] */ + do { + if (!BN_rand_range(msk->masterSecret, mpk->order)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(msk->masterSecret) || BN_is_one(msk->masterSecret)); + + /* mpk->pointPpub = msk->masterSecret * mpk->pointP */ + if (!EC_POINT_mul(group, point, msk->masterSecret, + NULL, NULL, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!(size = EC_POINT_point2oct(group, point, point_form, + NULL, 0, bn_ctx))) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(mpk->pointPpub, NULL, size)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!EC_POINT_point2oct(group, point, point_form, + mpk->pointPpub->data, mpk->pointPpub->length, bn_ctx)) { + SM9err(SM9_F_SM9_SETUP_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + + /* set return value */ + *pmpk = mpk; + *pmsk = msk; + ret = 1; + +end: + if (!ret) { + SM9PublicParameters_free(mpk); + SM9MasterSecret_free(msk); + *pmpk = NULL; + *pmsk = NULL; + } + BN_CTX_free(bn_ctx); + EC_POINT_free(point); + return ret; +} + +int SM9_setup_by_pairing_name(int nid, + SM9PublicParameters **mpk, SM9MasterSecret **msk) +{ + EC_GROUP *group = EC_GROUP_new_sm9s256t1(); + return SM9_setup_type1curve(group, EVP_sm3(), mpk, msk); +} + diff --git a/crypto/sm9/sm9_sign.c b/crypto/sm9/sm9_sign.c new file mode 100644 index 00000000..0c48cc4d --- /dev/null +++ b/crypto/sm9/sm9_sign.c @@ -0,0 +1,509 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include +#include +#include "sm9_lcl.h" + +static SM9Signature *SM9_do_sign_type1curve(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, SM9PrivateKey *sk) +{ + int e = 1; + SM9Signature *ret = NULL; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + BN_GFP2 *w = NULL; + unsigned char *buf = NULL; + BIGNUM *r; + BIGNUM *l; + const EVP_MD *md; + int point_form = POINT_CONVERSION_UNCOMPRESSED; + size_t size; + + if (!mpk || !dgst || dgstlen <= 0 || !sk) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, + ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (dgstlen > EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, + SM9_R_INVALID_DIGEST); + return NULL; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, + ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, + mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, + mpk->order, mpk->cofactor, bn_ctx))) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* malloc */ + ret = SM9Signature_new(); + point = EC_POINT_new(group); + r = BN_CTX_get(bn_ctx); + l = BN_CTX_get(bn_ctx); + + if (!ret || !point || !r || !l) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, SM9_R_INVALID_MD); + goto end; + } + + do { + /* rand r in [1, mpk->order - 1] */ + do { + if (!BN_rand_range(r, mpk->order)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(r)); + + /* get w = mpk->g = e(mpk->pointP1, mpk->pointPpub) */ + if (!BN_bn2gfp2(mpk->g1, w, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* w = w^r = (mpk->g)^r in F_p^2 */ + if (!BN_GFP2_exp(w, w, r, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* prepare w buf and canonical(w, order=0) */ + if (!BN_GFP2_canonical(w, NULL, &size, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + if (!(buf = OPENSSL_malloc(size))) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!BN_GFP2_canonical(w, buf, &size, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* ret->h = H2(H(m)||w) in range defined by mpk->order */ + if (!SM9_hash2(md, &ret->h, dgst, dgstlen, buf, size, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_SM9_LIB); + goto end; + } + + /* l = (r - ret->h) (mod mpk->order) */ + if (!BN_mod_sub(l, r, ret->h, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* if l == 0, re-generate r */ + } while (BN_is_zero(l)); + + /* point = sk->prointPoint */ + if (!EC_POINT_oct2point(group, point, + sk->privatePoint->data, sk->privatePoint->length, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + + /* sig->pointS = sk->privatePoint * l */ + if (!EC_POINT_mul(group, point, NULL, point, l, bn_ctx)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!(size = EC_POINT_point2oct(group, point, point_form, + NULL, 0, bn_ctx))) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!ASN1_OCTET_STRING_set(ret->pointS, NULL, size)) { + SM9err(SM9_F_SM9_DO_SIGN_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_point2oct(group, point, point_form, + ret->pointS->data, ret->pointS->length, bn_ctx)) { + goto end; + } + + e = 0; + +end: + if (e && ret) { + SM9Signature_free(ret); + ret = NULL; + } + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + BN_GFP2_free(w); + OPENSSL_free(buf); + return NULL; +} + +SM9Signature *SM9_do_sign(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + SM9PrivateKey *sk) +{ + if (!mpk || !dgst || dgstlen <= 0 || !sk) { + SM9err(SM9_F_SM9_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + if (OBJ_obj2nid(mpk->curve) == NID_type1curve) { + return SM9_do_sign_type1curve(mpk, dgst, dgstlen, sk); + } + + SM9err(SM9_F_SM9_DO_SIGN, SM9_R_INVALID_CURVE); + return NULL; +} + +int SM9_do_verify_type1curve(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + const SM9Signature *sig, const char *id, size_t idlen) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_POINT *pointS = NULL; + EC_POINT *Ppub = NULL; + BN_GFP2 *t = NULL; + BN_GFP2 *u = NULL; + BN_GFP2 *w = NULL; + unsigned char *buf = NULL; + BIGNUM *h1; + BIGNUM *h2; + size_t size; + const EVP_MD *md; + + if (!mpk || !dgst || dgstlen <= 0 || !sig || !id || idlen <= 0) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (dgstlen > EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_DIGEST); + return 0; + } + if (idlen > SM9_MAX_ID_LENGTH) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_ID); + return 0; + } + + /* BN_CTX */ + if (!(bn_ctx = BN_CTX_new())) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + BN_CTX_start(bn_ctx); + + /* EC_GROUP */ + if (!(group = EC_GROUP_new_type1curve_ex(mpk->p, + mpk->a, mpk->b, mpk->pointP1->data, mpk->pointP1->length, + mpk->order, mpk->cofactor, bn_ctx))) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + + /* malloc */ + point = EC_POINT_new(group); + pointS = EC_POINT_new(group); + Ppub = EC_POINT_new(group); + t = BN_GFP2_new(); + u = BN_GFP2_new(); + w = BN_GFP2_new(); + h1 = BN_CTX_get(bn_ctx); + h2 = BN_CTX_get(bn_ctx); + + if (!point || !pointS || !Ppub || !t || !u || !w || !h1 || !h2) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + + /* md = mpk->hashfcn */ + if (!(md = EVP_get_digestbyobj(mpk->hashfcn))) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_MD); + goto end; + } + + /* check sig->h in [1, mpk->order - 1] */ + //FIXME: do we need to check sig->h > 0 ? + if (BN_is_zero(sig->h) || BN_cmp(sig->h, mpk->order) >= 0) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_SIGNATURE); + goto end; + } + + /* pointS = sig->pointS */ + if (!EC_POINT_oct2point(group, pointS, + sig->pointS->data, sig->pointS->length, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_SIGNATURE); + goto end; + } + + /* decode t from mpk->g in F_p^2 */ + if (!BN_bn2gfp2(mpk->g1, t, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* t = t^(sig->h) = (mpk->g)^(sig->h) in F_p^2 */ + if (!BN_GFP2_exp(t, t, sig->h, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* h1 = H1(ID||hid) to range [0, mpk->order) */ + if (!SM9_hash1(md, &h1, id, idlen, SM9_HID, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_SM9_LIB); + goto end; + } + + /* point = mpk->pointP2 * h1 + mpk->pointPpub */ + if (!EC_POINT_mul(group, point, h1, NULL, NULL, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + if (!EC_POINT_oct2point(group, Ppub, + mpk->pointPpub->data, mpk->pointPpub->length, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_TYPE1CURVE); + goto end; + } + if (!EC_POINT_add(group, point, point, Ppub, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_EC_LIB); + goto end; + } + + /* u = e(sig->pointS, point) in F_p^2 */ + if (!EC_type1curve_tate(group, u, pointS, point, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_COMPUTE_PAIRING_FAILURE); + goto end; + } + + /* w = u * t in F_p^2 */ + if (!BN_GFP2_mul(w, u, t, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* buf = canonical(w) */ + if (!BN_GFP2_canonical(w, NULL, &size, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + if (!(buf = OPENSSL_malloc(size))) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_MALLOC_FAILURE); + goto end; + } + if (!BN_GFP2_canonical(w, buf, &size, 0, mpk->p, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, ERR_R_BN_LIB); + goto end; + } + + /* h2 = H2(M||w) in [0, mpk->order - 1] */ + if (!SM9_hash2(md, &h2, dgst, dgstlen, buf, size, mpk->order, bn_ctx)) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_HASH_FAILURE); + goto end; + } + + /* check if h2 == sig->h */ + if (BN_cmp(h2, sig->h) != 0) { + SM9err(SM9_F_SM9_DO_VERIFY_TYPE1CURVE, SM9_R_INVALID_SIGNATURE); + goto end; + } + + //FIXME: return value of sig verify + ret = 1; +end: + if (bn_ctx) { + BN_CTX_end(bn_ctx); + } + BN_CTX_free(bn_ctx); + EC_GROUP_free(group); + EC_POINT_free(point); + EC_POINT_free(pointS); + EC_POINT_free(Ppub); + BN_GFP2_free(t); + BN_GFP2_free(u); + BN_GFP2_free(w); + OPENSSL_free(buf); + return ret; +} + +int SM9_do_verify(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + const SM9Signature *sig, const char *id, size_t idlen) +{ + if (!mpk || !dgst || dgstlen <= 0 || !sig || !id || idlen <= 0) { + SM9err(SM9_F_SM9_DO_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (OBJ_obj2nid(mpk->curve) == NID_type1curve) { + return SM9_do_verify_type1curve(mpk, dgst, dgstlen, sig, id, idlen); + } + + SM9err(SM9_F_SM9_DO_VERIFY, SM9_R_INVALID_CURVE); + return 0; +} + +int SM9PublicParmeters_get_signature_size(void *a, void *b) +{ + return 0; +} + +int SM9_sign(SM9PublicParameters *mpk, const unsigned char *dgst, + size_t dgstlen, unsigned char *sig, size_t *siglen, + SM9PrivateKey *sk) +{ + int ret = 0; + SM9Signature *sigobj = NULL; + unsigned char *p; + size_t sigsiz; + + if (!mpk || !dgst || !siglen || !sk) { + SM9err(SM9_F_SM9_SIGN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (dgstlen <= 0 || dgstlen > EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9_SIGN, SM9_R_INVALID_DIGEST_LENGTH); + return 0; + } + + /* compute output signature size */ + if (!SM9PublicParmeters_get_signature_size(mpk, &sigsiz)) { + SM9err(SM9_F_SM9_SIGN, ERR_R_SM9_LIB); + return 0; + } + + if (!sig) { + *siglen = sigsiz; + return 1; + } + if (*siglen < sigsiz) { + SM9err(SM9_F_SM9_SIGN, SM9_R_BUFFER_TOO_SMALL); + return 0; + } + + /* do_sign */ + if (!(sigobj = SM9_do_sign(mpk, dgst, dgstlen, sk))) { + SM9err(SM9_F_SM9_SIGN, ERR_R_SM9_LIB); + return 0; + } + + p = &sig; + if (i2d_SM9Signature(sigobj, &p) < 0) { + SM9err(SM9_F_SM9_SIGN, ERR_R_SM9_LIB); + goto end; + } + + *siglen = p - sig; + ret = 1; + +end: + SM9Signature_free(sigobj); + return ret; +} + + +int SM9_verify(SM9PublicParameters *mpk, const unsigned char *dgst, + size_t dgstlen, const unsigned char *sig, size_t siglen, + const char *id, size_t idlen) +{ + int ret = -1; + SM9Signature *sigobj = NULL; + const unsigned char *p; + + if (!mpk || !dgst || !sig || !id) { + SM9err(SM9_F_SM9_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (dgstlen <= 0 || dgstlen > EVP_MAX_MD_SIZE) { + SM9err(SM9_F_SM9_VERIFY, SM9_R_INVALID_DIGEST_LENGTH); + return 0; + } + if (idlen <= 0 || idlen > SM9_MAX_ID_LENGTH || strlen(id) != idlen) { + SM9err(SM9_F_SM9_VERIFY, SM9_R_INVALID_ID_LENGTH); + return 0; + } + + p = &sig; + if (!(sigobj = d2i_SM9Signature(NULL, &p, siglen))) { + SM9err(SM9_F_SM9_VERIFY, ERR_R_SM9_LIB); + return 0; + } + + ret = SM9_do_verify(mpk, dgst, dgstlen, sigobj, id, idlen); + + +end: + SM9Signature_free(sigobj); + return 0; +} + diff --git a/include/openssl/bb1ibe.h b/include/openssl/bb1ibe.h new file mode 100644 index 00000000..e2a6321e --- /dev/null +++ b/include/openssl/bb1ibe.h @@ -0,0 +1,144 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ +/* + * Boneh-Boyen Identity-Based Encryption (BB1-IBE) + * see [RFC 5091](https://tools.ietf.org/html/rfc5091) + * Identity-Based Cryptography Standard (IBCS) #1: + * Supersingular Curve Implementations of the BF and BB1 Cryptosystems + */ + +#ifndef HEADER_BB1IBE_H +#define HEADER_BB1IBE_H + +#include +#include +#include +#include +#include +#include + +#define BB1IBE_VERSION 2 + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct BB1PublicParameters_st BB1PublicParameters; +typedef struct BB1MasterSecret_st BB1MasterSecret; +typedef struct BB1PrivateKeyBlock_st BB1PrivateKeyBlock; +typedef struct BB1CiphertextBlock_st BB1CiphertextBlock; + + +int BB1IBE_setup(const EC_GROUP *group, const EVP_MD *md, + BB1PublicParameters **mpk, BB1MasterSecret **msk); +BB1PrivateKeyBlock *BB1IBE_extract_private_key(BB1PublicParameters *mpk, + BB1MasterSecret *msk, const char *id, size_t idlen); +BB1CiphertextBlock *BB1IBE_do_encrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen); +int BB1IBE_do_decrypt(BB1PublicParameters *mpk, + const BB1CiphertextBlock *in, unsigned char *out, size_t *outlen, + BB1PrivateKeyBlock *sk); +int BB1IBE_encrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen); +int BB1IBE_decrypt(BB1PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + BB1PrivateKeyBlock *sk); + +DECLARE_ASN1_FUNCTIONS(BB1MasterSecret) +DECLARE_ASN1_FUNCTIONS(BB1PublicParameters) +DECLARE_ASN1_FUNCTIONS(BB1PrivateKeyBlock) +DECLARE_ASN1_FUNCTIONS(BB1CiphertextBlock) + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +int ERR_load_BB1IBE_strings(void); + +/* Error codes for the BB1IBE functions. */ + +/* Function codes. */ +# define BB1IBE_F_BB1CIPHERTEXTBLOCK_HASH_TO_RANGE 100 +# define BB1IBE_F_BB1IBE_DECRYPT 101 +# define BB1IBE_F_BB1IBE_DOUBLE_HASH 102 +# define BB1IBE_F_BB1IBE_DO_DECRYPT 103 +# define BB1IBE_F_BB1IBE_DO_ENCRYPT 104 +# define BB1IBE_F_BB1IBE_ENCRYPT 105 +# define BB1IBE_F_BB1IBE_EXTRACT_PRIVATE_KEY 106 +# define BB1IBE_F_BB1IBE_SETUP 107 + +/* Reason codes. */ +# define BB1IBE_R_BB1CIPHERTEXT_INVALID_MAC 100 +# define BB1IBE_R_BB1IBE_HASH_FAILURE 101 +# define BB1IBE_R_BUFFER_TOO_SMALL 102 +# define BB1IBE_R_COMPUTE_OUTLEN_FAILURE 103 +# define BB1IBE_R_COMPUTE_TATE_FAILURE 104 +# define BB1IBE_R_D2I_FAILURE 105 +# define BB1IBE_R_DECRYPT_FAILURE 106 +# define BB1IBE_R_DOUBLE_HASH_FAILURE 107 +# define BB1IBE_R_ENCRYPT_FAILURE 108 +# define BB1IBE_R_I2D_FAILURE 109 +# define BB1IBE_R_INVALID_INPUT 110 +# define BB1IBE_R_INVALID_MD 111 +# define BB1IBE_R_INVALID_OUTPUT_BUFFER 112 +# define BB1IBE_R_INVALID_TYPE1CURVE 113 +# define BB1IBE_R_NOT_NAMED_CURVE 114 +# define BB1IBE_R_PARSE_PAIRING 115 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/include/openssl/bfibe.h b/include/openssl/bfibe.h new file mode 100644 index 00000000..5675b785 --- /dev/null +++ b/include/openssl/bfibe.h @@ -0,0 +1,142 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ +/* + * Boneh-Franklin Identity-Based Encryption (BF-IBE) + * see [RFC 5091](https://tools.ietf.org/html/rfc5091) + * Identity-Based Cryptography Standard (IBCS) #1: + * Supersingular Curve Implementations of the BF and BB1 Cryptosystems + */ + +#ifndef HEADER_BFIBE_H +#define HEADER_BFIBE_H + +#include +#include +#include +#include +#include +#include + +#define BFIBE_VERSION 2 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BFPublicParameters_st BFPublicParameters; +typedef struct BFMasterSecret_st BFMasterSecret; +typedef struct BFPrivateKeyBlock_st BFPrivateKeyBlock; +typedef struct BFCiphertextBlock_st BFCiphertextBlock; + +int BFIBE_setup(const EC_GROUP *group, const EVP_MD *md, + BFPublicParameters **mpk, BFMasterSecret **msk); +BFPrivateKeyBlock *BFIBE_extract_private_key(BFPublicParameters *mpk, + BFMasterSecret *msk, const char *id, size_t idlen); +BFCiphertextBlock *BFIBE_do_encrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen); +int BFIBE_do_decrypt(BFPublicParameters *mpk, + const BFCiphertextBlock *in, + unsigned char *out, size_t *outlen, + BFPrivateKeyBlock *sk); +int BFIBE_encrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen); +int BFIBE_decrypt(BFPublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + BFPrivateKeyBlock *sk); + +DECLARE_ASN1_FUNCTIONS(BFPublicParameters) +DECLARE_ASN1_FUNCTIONS(BFMasterSecret) +DECLARE_ASN1_FUNCTIONS(BFPrivateKeyBlock) +DECLARE_ASN1_FUNCTIONS(BFCiphertextBlock) + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +int ERR_load_BFIBE_strings(void); + +/* Error codes for the BFIBE functions. */ + +/* Function codes. */ +# define BFIBE_F_BFIBE_DECRYPT 100 +# define BFIBE_F_BFIBE_DO_DECRYPT 101 +# define BFIBE_F_BFIBE_DO_ENCRYPT 102 +# define BFIBE_F_BFIBE_ENCRYPT 103 +# define BFIBE_F_BFIBE_EXTRACT_PRIVATE_KEY 104 +# define BFIBE_F_BFIBE_SETUP 105 + +/* Reason codes. */ +# define BFIBE_R_BFIBE_CIPHERTEXT_FAILURE 100 +# define BFIBE_R_BUFFER_TOO_SMALL 101 +# define BFIBE_R_COMPUTE_OUTLEN_FAILURE 102 +# define BFIBE_R_D2I_FAILURE 103 +# define BFIBE_R_DECRYPT_FAILURE 104 +# define BFIBE_R_ENCRYPT_FAILURE 105 +# define BFIBE_R_HASH_BYTES_FAILURE 106 +# define BFIBE_R_I2D_FAILURE 107 +# define BFIBE_R_INVALID_BFIBE_HASHFUNC 108 +# define BFIBE_R_INVALID_CIPHERTEXT 109 +# define BFIBE_R_INVALID_TYPE1CURVE 110 +# define BFIBE_R_KDF_FAILURE 111 +# define BFIBE_R_NOT_NAMED_CURVE 112 +# define BFIBE_R_PARSE_CURVE_FAILURE 113 +# define BFIBE_R_PARSE_MPK_FAILURE 114 +# define BFIBE_R_PARSE_PAIRING 115 +# define BFIBE_R_RAND_FAILURE 116 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/include/openssl/err.h b/include/openssl/err.h index 86b599d8..0666afe5 100644 --- a/include/openssl/err.h +++ b/include/openssl/err.h @@ -99,6 +99,9 @@ typedef struct err_state_st { # define ERR_LIB_CPK 56 # define ERR_LIB_OTP 57 # define ERR_LIB_GMAPI 58 +# define ERR_LIB_BFIBE 59 +# define ERR_LIB_BB1IBE 60 +# define ERR_LIB_SM9 61 # define ERR_LIB_USER 128 @@ -143,6 +146,9 @@ typedef struct err_state_st { # define CPKerr(f,r) ERR_PUT_error(ERR_LIB_CPK,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define OTPerr(f,r) ERR_PUT_error(ERR_LIB_OTP,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define GMAPIerr(f,r) ERR_PUT_error(ERR_LIB_GMAPI,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BFIBEerr(f,r) ERR_PUT_error(ERR_LIB_BFIBE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define BB1IBEerr(f,r) ERR_PUT_error(ERR_LIB_BB1IBE,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define SM9err(f,r) ERR_PUT_error(ERR_LIB_SM9,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define ERR_PACK(l,f,r) ( \ (((unsigned int)(l) & 0x0FF) << 24L) | \ @@ -196,6 +202,11 @@ typedef struct err_state_st { # define ERR_R_CPK_LIB ERR_LIB_CPK/* 56 */ # define ERR_R_OTP_LIB ERR_LIB_OTP/* 57 */ # define ERR_R_GMAPI_LIB ERR_LIB_GMAPI/* 58 */ +# define ERR_R_BFIBE_LIB ERR_LIB_BFIBE/* 59 */ +# define ERR_R_BB1IBE_LIB ERR_LIB_BB1IBE/* 60 */ +# define ERR_R_SM9_LIB ERR_LIB_SM9/* 61 */ + +# define ERR_R_NESTED_ASN1_ERROR 58 # define ERR_R_NESTED_ASN1_ERROR 58 # define ERR_R_MISSING_ASN1_EOS 63 diff --git a/include/openssl/sm9.h b/include/openssl/sm9.h new file mode 100644 index 00000000..8263bebf --- /dev/null +++ b/include/openssl/sm9.h @@ -0,0 +1,205 @@ +/* ==================================================================== + * Copyright (c) 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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. + * ==================================================================== + */ + +#ifndef HEADER_SM9_H +#define HEADER_SM9_H + +#include +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SM9PublicParameters_st SM9PublicParameters; +typedef struct SM9MasterSecret_st SM9MasterSecret; +typedef struct SM9PrivateKey_st SM9PrivateKey; +typedef struct SM9Ciphertext_st SM9Ciphertext; +typedef struct SM9Signature_st SM9Signature; + +int SM9_setup_by_pairing_name(int nid, + SM9PublicParameters **mpk, + SM9MasterSecret **msk); + +SM9PrivateKey *SM9_extract_private_key(SM9PublicParameters *mpk, + SM9MasterSecret *msk, + const char *id, size_t idlen); + +typedef struct { + const EVP_MD *kdf_md; + const EVP_CIPHER *enc_cipher; + const EVP_CIPHER *cmac_cipher; + const EVP_CIPHER *cbcmac_cipher; + const EVP_MD *hmac_md; +} SM9EncParameters; + +SM9Ciphertext *SM9_do_encrypt(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + const char *id, size_t idlen); + +int SM9_do_decrypt(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, + const SM9Ciphertext *in, + unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, + const char *id, size_t idlen); + +int SM9_encrypt(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen); + +int SM9_decrypt(SM9PublicParameters *mpk, + const SM9EncParameters *encparams, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, + const char *id, size_t idlen); + +int SM9_encrypt_with_recommended(SM9PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + const char *id, size_t idlen); + +int SM9_decrypt_with_recommended(SM9PublicParameters *mpk, + const unsigned char *in, size_t inlen, + unsigned char *out, size_t *outlen, + SM9PrivateKey *sk, + const char *id, size_t idlen); + +SM9Signature *SM9_do_sign(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + SM9PrivateKey *sk); + +int SM9_do_verify(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + const SM9Signature *sig, + const char *id, size_t idlen); + +int SM9_sign(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + unsigned char *sig, size_t *siglen, + SM9PrivateKey *sk); + +int SM9_verify(SM9PublicParameters *mpk, + const unsigned char *dgst, size_t dgstlen, + const unsigned char *sig, size_t siglen, + const char *id, size_t idlen); + +DECLARE_ASN1_FUNCTIONS(SM9PublicParameters) +DECLARE_ASN1_FUNCTIONS(SM9MasterSecret) +DECLARE_ASN1_FUNCTIONS(SM9PrivateKey) +DECLARE_ASN1_FUNCTIONS(SM9Ciphertext) +DECLARE_ASN1_FUNCTIONS(SM9Signature) + + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +int ERR_load_SM9_strings(void); + +/* Error codes for the SM9 functions. */ + +/* Function codes. */ +# define SM9_F_SM9CIPHERTEXT_CHECK 100 +# define SM9_F_SM9ENCPARAMETERS_DECRYPT 101 +# define SM9_F_SM9ENCPARAMETERS_ENCRYPT 102 +# define SM9_F_SM9ENCPARAMETERS_GENERATE_MAC 103 +# define SM9_F_SM9ENCPARAMETERS_GET_KEY_LENGTH 104 +# define SM9_F_SM9PUBLICPARAMETERS_GET_POINT_SIZE 105 +# define SM9_F_SM9_DECRYPT 106 +# define SM9_F_SM9_DO_DECRYPT 107 +# define SM9_F_SM9_DO_ENCRYPT 108 +# define SM9_F_SM9_DO_SIGN 109 +# define SM9_F_SM9_DO_SIGN_TYPE1CURVE 110 +# define SM9_F_SM9_DO_VERIFY 111 +# define SM9_F_SM9_DO_VERIFY_TYPE1CURVE 112 +# define SM9_F_SM9_ENCRYPT 113 +# define SM9_F_SM9_EXTRACT_PRIVATE_KEY 114 +# define SM9_F_SM9_SETUP_TYPE1CURVE 115 +# define SM9_F_SM9_SIGN 116 +# define SM9_F_SM9_UNWRAP_KEY 117 +# define SM9_F_SM9_VERIFY 118 +# define SM9_F_SM9_WRAP_KEY 119 + +/* Reason codes. */ +# define SM9_R_BUFFER_TOO_SMALL 100 +# define SM9_R_COMPUTE_PAIRING_FAILURE 101 +# define SM9_R_GENERATE_MAC_FAILURE 102 +# define SM9_R_HASH_FAILURE 103 +# define SM9_R_INVALID_CIPHERTEXT 104 +# define SM9_R_INVALID_CURVE 105 +# define SM9_R_INVALID_DIGEST 106 +# define SM9_R_INVALID_DIGEST_LENGTH 107 +# define SM9_R_INVALID_ENCPARAMETERS 108 +# define SM9_R_INVALID_ID 109 +# define SM9_R_INVALID_ID_LENGTH 110 +# define SM9_R_INVALID_INPUT 111 +# define SM9_R_INVALID_KEY_LENGTH 112 +# define SM9_R_INVALID_MD 113 +# define SM9_R_INVALID_PARAMETER 114 +# define SM9_R_INVALID_SIGNATURE 115 +# define SM9_R_INVALID_TYPE1CURVE 116 +# define SM9_R_KDF_FAILURE 117 +# define SM9_R_NOT_NAMED_CURVE 118 +# define SM9_R_PARSE_PAIRING 119 +# define SM9_R_ZERO_ID 120 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/test/bb1ibetest.c b/test/bb1ibetest.c new file mode 100644 index 00000000..1edcb5f7 --- /dev/null +++ b/test/bb1ibetest.c @@ -0,0 +1,132 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include "../e_os.h" + +#ifdef OPENSSL_NO_BB1IBE +int main(int argc, char **argv) +{ + printf("NO BB1IBE support\n"); + return 0; +} +#else +# include +# include + +int main(int argc, char **argv) +{ + int err = 1; + int curve_id = NID_sm2p256v1;//FIXME + const EVP_MD *md = EVP_sm3(); + char *id = "guanzhi1980@gmail.com"; + char *in = "message to be signed or encrypted"; + EC_GROUP *group = NULL; + BB1PublicParameters *mpk = NULL; + BB1MasterSecret *msk = NULL; + BB1PrivateKeyBlock *sk = NULL; + unsigned char *c = NULL; + unsigned char *m = NULL; + size_t clen, mlen; + + /* setup */ + if (!(group = EC_GROUP_new_by_curve_name(curve_id))) { + goto end; + } + if (!BB1IBE_setup(group, md, &mpk, &msk)) { + goto end; + } + + /* keygen */ + if (!(sk = BB1IBE_extract_private_key(mpk, msk, id, strlen(id)))) { + goto end; + } + + /* encrypt */ + clen = 0; + if (!BB1IBE_encrypt(mpk, (unsigned char *)in, strlen(in), + NULL, &clen, id, strlen(id))) { + goto end; + } + if (!(c = OPENSSL_zalloc(clen))) { + goto end; + } + if (!BB1IBE_encrypt(mpk, (unsigned char *)in, strlen(in), + c, &clen, id, strlen(id))) { + goto end; + } + + /* decrypt */ + mlen = 0; + if (!BB1IBE_decrypt(mpk, c, clen, NULL, &mlen, sk)) { + goto end; + } + if (!(m = OPENSSL_zalloc(mlen))) { + goto end; + } + if (!BB1IBE_decrypt(mpk, c, clen, m, &mlen, sk)) { + goto end; + } + if (strlen(in) != mlen || memcmp(in, m, mlen) != 0) { + goto end; + } + + err = 0; +end: + EC_GROUP_free(group); + BB1PublicParameters_free(mpk); + BB1MasterSecret_free(msk); + BB1PrivateKeyBlock_free(sk); + OPENSSL_free(c); + OPENSSL_free(m); + return err; +} +#endif diff --git a/test/bfibetest.c b/test/bfibetest.c new file mode 100644 index 00000000..acb2ce3a --- /dev/null +++ b/test/bfibetest.c @@ -0,0 +1,132 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include "../e_os.h" + +#ifdef OPENSSL_NO_BFIBE +int main(int argc, char **argv) +{ + printf("NO BFIBE support\n"); + return 0; +} +#else +# include +# include + +int main(int argc, char **argv) +{ + int err = 1; + int curve_id = NID_sm2p256v1; + const EVP_MD *md = EVP_sm3(); + char *id = "guanzhi1980@gmail.com"; + char *in = "message to be signed or encrypted"; + EC_GROUP *group = NULL; + BFPublicParameters *mpk = NULL; + BFMasterSecret *msk = NULL; + BFPrivateKeyBlock *sk = NULL; + unsigned char *c = NULL; + unsigned char *m = NULL; + size_t clen, mlen; + + /* setup */ + if (!(group = EC_GROUP_new_by_curve_name(curve_id))) { + goto end; + } + if (!BFIBE_setup(group, md, &mpk, &msk)) { + goto end; + } + + /* keygen */ + if (!(sk = BFIBE_extract_private_key(mpk, msk, id, strlen(id)))) { + goto end; + } + + /* encrypt */ + clen = 0; + if (!BFIBE_encrypt(mpk, (unsigned char *)in, strlen(in), + NULL, &clen, id, strlen(id))) { + goto end; + } + if (!(c = OPENSSL_zalloc(clen))) { + goto end; + } + if (!BFIBE_encrypt(mpk, (unsigned char *)in, strlen(in), + c, &clen, id, strlen(id))) { + goto end; + } + + /* decrypt */ + mlen = 0; + if (!BFIBE_decrypt(mpk, c, clen, NULL, &mlen, sk)) { + goto end; + } + if (!(m = OPENSSL_zalloc(mlen))) { + goto end; + } + if (!BFIBE_decrypt(mpk, c, clen, m, &mlen, sk)) { + goto end; + } + if (strlen(in) != mlen || memcmp(in, m, mlen) != 0) { + goto end; + } + + err = 0; +end: + EC_GROUP_free(group); + BFPublicParameters_free(mpk); + BFMasterSecret_free(msk); + BFPrivateKeyBlock_free(sk); + OPENSSL_free(c); + OPENSSL_free(m); + return err; +} +#endif diff --git a/test/build.info b/test/build.info index 64e95cbe..572d8703 100644 --- a/test/build.info +++ b/test/build.info @@ -18,7 +18,8 @@ IF[{- !$disabled{tests} -}] ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \ bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \ sm3test sms4test kdf2test eciestest ffxtest sm2test \ - pailliertest cpktest otptest gmapitest ec2test + pailliertest cpktest otptest gmapitest ec2test \ + bfibetest bb1ibetest sm9test SOURCE[aborttest]=aborttest.c INCLUDE[aborttest]=../include @@ -329,6 +330,18 @@ IF[{- !$disabled{tests} -}] INCLUDE[ec2test]=../include DEPEND[ec2test]=../libcrypto + SOURCE[bfibetest]=bfibetest.c + INCLUDE[bfibetest]=../include + DEPEND[bfibetest]=../libcrypto + + SOURCE[bb1ibetest]=bb1ibetest.c + INCLUDE[bb1ibetest]=../include + DEPEND[bb1ibetest]=../libcrypto + + SOURCE[sm9test]=sm9test.c + INCLUDE[sm9test]=../include + DEPEND[sm9test]=../libcrypto + IF[{- !$disabled{shared} -}] PROGRAMS_NO_INST=shlibloadtest SOURCE[shlibloadtest]=shlibloadtest.c diff --git a/test/recipes/15-test_bb1ibe.t b/test/recipes/15-test_bb1ibe.t new file mode 100644 index 00000000..1e7c76d5 --- /dev/null +++ b/test/recipes/15-test_bb1ibe.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use OpenSSL::Test::Simple; + +simple_test("test_bb1ibe", "bb1ibetest", "bb1ibe"); diff --git a/test/recipes/15-test_bfibe.t b/test/recipes/15-test_bfibe.t new file mode 100644 index 00000000..7f8f58f9 --- /dev/null +++ b/test/recipes/15-test_bfibe.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use OpenSSL::Test::Simple; + +simple_test("test_bfibe", "bfibetest", "bfibe"); diff --git a/test/recipes/15-test_sm9.t b/test/recipes/15-test_sm9.t new file mode 100644 index 00000000..767b0217 --- /dev/null +++ b/test/recipes/15-test_sm9.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use OpenSSL::Test::Simple; + +simple_test("test_sm9", "sm9test", "sm9"); diff --git a/test/sm9test.c b/test/sm9test.c new file mode 100644 index 00000000..749937e8 --- /dev/null +++ b/test/sm9test.c @@ -0,0 +1,149 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2016 The GmSSL 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 GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL 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 GmSSL 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 +#include +#include +#include "../e_os.h" + +#ifdef OPENSSL_NO_SM9 +int main(int argc, char **argv) +{ + printf("NO SM9 support\n"); + return 0; +} +#else +# include +# include + +int main(int argc, char **argv) +{ + int err = 1; + int curve_id = NID_sm2p256v1; //FIXME + char *id = "guanzhi1980@gmail.com"; + char *in = "message to be signed or encrypted"; + SM9PublicParameters *mpk = NULL; + SM9MasterSecret *msk = NULL; + SM9PrivateKey *sk = NULL; + unsigned char dgst[32] = {0x01, 0x00}; + unsigned char *c = NULL; + unsigned char *m = NULL; + unsigned char *sig = NULL; + size_t clen, mlen, siglen; + + /* setup */ + if (!SM9_setup_by_pairing_name(curve_id, &mpk, &msk)) { + goto end; + } + + /* keygen */ + if (!(sk = SM9_extract_private_key(mpk, msk, id, strlen(id)))) { + goto end; + } + + /* encrypt */ + clen = 0; + if (!SM9_encrypt_with_recommended(mpk, (unsigned char *)in, + strlen(in), NULL, &clen, id, strlen(id))) { + goto end; + } + if (!(c = OPENSSL_zalloc(clen))) { + goto end; + } + if (!SM9_encrypt_with_recommended(mpk, (unsigned char *)in, + strlen(in), c, &clen, id, strlen(id))) { + goto end; + } + + /* decrypt */ + mlen = 0; + if (!SM9_decrypt_with_recommended(mpk, c, clen, NULL, &mlen, + sk, id, strlen(id))) { + goto end; + } + if (!(m = OPENSSL_zalloc(mlen))) { + goto end; + } + if (!SM9_decrypt_with_recommended(mpk, c, clen, m, &mlen, + sk, id, strlen(id))) { + goto end; + } + if (strlen(in) != mlen || memcmp(in, m, mlen) != 0) { + goto end; + } + + /* sign */ + siglen = 0; + if (!SM9_sign(mpk, dgst, sizeof(dgst), NULL, &siglen, sk)) { + goto end; + } + if (!(sig = OPENSSL_zalloc(siglen))) { + goto end; + } + if (!SM9_sign(mpk, dgst, sizeof(dgst), sig, &siglen, sk)) { + goto end; + } + + /* verify */ + if (1 != SM9_verify(mpk, dgst, sizeof(dgst), sig, siglen, + id, strlen(id))) { + goto end; + } + + err = 0; +end: + SM9PublicParameters_free(mpk); + SM9MasterSecret_free(msk); + SM9PrivateKey_free(sk); + OPENSSL_free(c); + OPENSSL_free(m); + OPENSSL_free(sig); + return err; +} +#endif diff --git a/util/mkdef.pl b/util/mkdef.pl index 1c372c1a..8d1ede68 100755 --- a/util/mkdef.pl +++ b/util/mkdef.pl @@ -132,7 +132,8 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF", "CMAC", # APPLINK (win build feature?) "APPLINK", - "SM3", "SMS4", "KDF2", "ECIES", "FFX", "PAILLIER", "CPK", "OTP", "GMAPI" + "SM3", "SMS4", "KDF2", "ECIES", "FFX", "PAILLIER", "CPK", "OTP", "GMAPI", "EC2", + "BFIBE", "BB1IBE", "SM9" ); my %disabled_algorithms;