From d94333174668659f4177f59f1a6369cb6ee3e06e Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Wed, 15 Feb 2017 14:50:44 +0800 Subject: [PATCH] add paillier --- Configure | 2 +- crypto/err/err.c | 2 + crypto/err/err_all.c | 4 + crypto/err/openssl.ec | 1 + crypto/paillier/build.info | 2 + crypto/paillier/pai_asn1.c | 84 ++++++++ crypto/paillier/pai_err.c | 53 +++++ crypto/paillier/pai_lcl.h | 63 ++++++ crypto/paillier/pai_lib.c | 347 ++++++++++++++++++++++++++++++++ include/openssl/err.h | 3 + include/openssl/paillier.h | 109 ++++++++++ test/build.info | 10 +- test/pailliertest.c | 184 +++++++++++++++++ test/recipes/15-test_paillier.t | 12 ++ util/mkdef.pl | 2 +- 15 files changed, 875 insertions(+), 3 deletions(-) create mode 100644 crypto/paillier/build.info create mode 100644 crypto/paillier/pai_asn1.c create mode 100644 crypto/paillier/pai_err.c create mode 100644 crypto/paillier/pai_lcl.h create mode 100644 crypto/paillier/pai_lib.c create mode 100644 include/openssl/paillier.h create mode 100644 test/pailliertest.c create mode 100644 test/recipes/15-test_paillier.t diff --git a/Configure b/Configure index 2b35229b..55bb136a 100755 --- a/Configure +++ b/Configure @@ -311,7 +311,7 @@ $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" + "sm3", "sms4", "kdf2", "ecies", "ffx", "sm2", "paillier" ]; # Known TLS and DTLS protocols diff --git a/crypto/err/err.c b/crypto/err/err.c index 1f827e1a..8061d847 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -61,6 +61,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"}, {ERR_PACK(ERR_LIB_KDF2, 0, 0), "KDF2 routines"}, {ERR_PACK(ERR_LIB_FFX, 0, 0), "FFX routines"}, + {ERR_PACK(ERR_LIB_PAILLIER, 0, 0), "PAILLIER routines"}, {0, NULL}, }; @@ -107,6 +108,7 @@ static ERR_STRING_DATA ERR_str_reasons[] = { {ERR_R_ECDSA_LIB, "ECDSA lib"}, {ERR_R_KDF2_LIB, "KDF2 lib"}, {ERR_R_FFX_LIB, "FFX lib"}, + {ERR_R_PAILLIER_LIB, "PAILLIER 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 de6bb245..d53fc249 100644 --- a/crypto/err/err_all.c +++ b/crypto/err/err_all.c @@ -41,6 +41,7 @@ #include #include #include +#include int err_load_crypto_strings_int(void) { @@ -109,6 +110,9 @@ int err_load_crypto_strings_int(void) # ifndef OPENSSL_NO_FFX ERR_load_FFX_strings() == 0 || # endif +# ifndef OPENSSL_NO_PAILLIER + ERR_load_PAILLIER_strings() == 0 || +# endif #endif ERR_load_KDF_strings() == 0) return 0; diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec index 408eff2a..1276ef4e 100644 --- a/crypto/err/openssl.ec +++ b/crypto/err/openssl.ec @@ -37,6 +37,7 @@ L ASYNC include/openssl/async.h crypto/async/async_err.c L KDF include/openssl/kdf.h crypto/kdf/kdf_err.c L KDF2 include/openssl/kdf2.h crypto/kdf2/kdf2_err.c L FFX include/openssl/ffx.h crypto/ffx/ffx_err.c +L PAILLIER include/openssl/paillier.h crypto/paillier/paillier_err.c # additional header files to be scanned for function names L NONE crypto/x509/x509_vfy.h NONE diff --git a/crypto/paillier/build.info b/crypto/paillier/build.info new file mode 100644 index 00000000..f669f9e5 --- /dev/null +++ b/crypto/paillier/build.info @@ -0,0 +1,2 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=pai_lib.c pai_err.c pai_asn1.c diff --git a/crypto/paillier/pai_asn1.c b/crypto/paillier/pai_asn1.c new file mode 100644 index 00000000..3e5bcc6f --- /dev/null +++ b/crypto/paillier/pai_asn1.c @@ -0,0 +1,84 @@ +/* ==================================================================== + * Copyright (c) 2015 - 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 "pai_lcl.h" + +static int paillier_cb(int operation, ASN1_VALUE **pval, + const ASN1_ITEM *it, void *exarg) +{ + if (operation == ASN1_OP_NEW_PRE) { + *pval = (ASN1_VALUE *)PAILLIER_new(); + if (*pval) + return 2; + return 0; + } else if (operation == ASN1_OP_FREE_PRE) { + PAILLIER_free((PAILLIER *)*pval); + *pval = NULL; + return 2; + } + return 1; +} + +ASN1_SEQUENCE_cb(PAILLIER_PRIVATE_KEY, paillier_cb) = { + ASN1_SIMPLE(PAILLIER, n, BIGNUM), + ASN1_SIMPLE(PAILLIER, lambda, BIGNUM), + ASN1_SIMPLE(PAILLIER, x, BIGNUM) +} ASN1_SEQUENCE_END_cb(PAILLIER, PAILLIER_PRIVATE_KEY) + +ASN1_SEQUENCE_cb(PAILLIER_PUBLIC_KEY, paillier_cb) = { + ASN1_SIMPLE(PAILLIER, n, BIGNUM) +} ASN1_SEQUENCE_END_cb(PAILLIER, PAILLIER_PUBLIC_KEY) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(PAILLIER, PAILLIER_PRIVATE_KEY, PAILLIER_PRIVATE_KEY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(PAILLIER, PAILLIER_PUBLIC_KEY, PAILLIER_PUBLIC_KEY) diff --git a/crypto/paillier/pai_err.c b/crypto/paillier/pai_err.c new file mode 100644 index 00000000..15f9f584 --- /dev/null +++ b/crypto/paillier/pai_err.c @@ -0,0 +1,53 @@ +/* + * 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_PAILLIER,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_PAILLIER,0,reason) + +static ERR_STRING_DATA PAILLIER_str_functs[] = { + {ERR_FUNC(PAILLIER_F_PAILLIER_CHECK_KEY), "PAILLIER_check_key"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD), "PAILLIER_ciphertext_add"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL), + "PAILLIER_ciphertext_scalar_mul"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_DECRYPT), "PAILLIER_decrypt"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_ENCRYPT), "PAILLIER_encrypt"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_GENERATE_KEY), "PAILLIER_generate_key"}, + {ERR_FUNC(PAILLIER_F_PAILLIER_NEW), "PAILLIER_new"}, + {0, NULL} +}; + +static ERR_STRING_DATA PAILLIER_str_reasons[] = { + {ERR_REASON(PAILLIER_R_GENERATE_PRIME_FAILED), "generate prime failed"}, + {ERR_REASON(PAILLIER_R_INVALID_PLAINTEXT), "invalid plaintext"}, + {ERR_REASON(PAILLIER_R_MALLOC_FAILED), "malloc failed"}, + {ERR_REASON(PAILLIER_R_NOT_IMPLEMENTED), "not implemented"}, + {0, NULL} +}; + +#endif + +int ERR_load_PAILLIER_strings(void) +{ +#ifndef OPENSSL_NO_ERR + + if (ERR_func_error_string(PAILLIER_str_functs[0].error) == NULL) { + ERR_load_strings(0, PAILLIER_str_functs); + ERR_load_strings(0, PAILLIER_str_reasons); + } +#endif + return 1; +} diff --git a/crypto/paillier/pai_lcl.h b/crypto/paillier/pai_lcl.h new file mode 100644 index 00000000..4fe78f1d --- /dev/null +++ b/crypto/paillier/pai_lcl.h @@ -0,0 +1,63 @@ +/* ==================================================================== + * Copyright (c) 2015 - 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_PAI_LCL_H +#define HEADER_PAI_LCL_H + +struct paillier_st { + int bits; + BIGNUM *n; /* public key */ + BIGNUM *lambda; /* private key, lambda(n) = lcm(p-1, q-1) */ + BIGNUM *n_squared; /* online */ + BIGNUM *n_plusone; /* online */ + BIGNUM *x; /* online */ +}; + +#endif + diff --git a/crypto/paillier/pai_lib.c b/crypto/paillier/pai_lib.c new file mode 100644 index 00000000..6b6b68be --- /dev/null +++ b/crypto/paillier/pai_lib.c @@ -0,0 +1,347 @@ +/* ==================================================================== + * Copyright (c) 2015 - 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 "pai_lcl.h" + +PAILLIER *PAILLIER_new(void) +{ + PAILLIER *ret = NULL; + + if (!(ret = OPENSSL_zalloc(sizeof(*ret)))) { + PAILLIERerr(PAILLIER_F_PAILLIER_NEW, PAILLIER_R_MALLOC_FAILED); + return NULL; + } + + return ret; +} + +void PAILLIER_free(PAILLIER *key) +{ + + if (key) { + BN_free(key->n); + BN_free(key->lambda); + BN_free(key->n_squared); + BN_free(key->n_plusone); + BN_free(key->x); + } + OPENSSL_clear_free(key, sizeof(*key)); +} + +int PAILLIER_generate_key(PAILLIER *key, int bits) +{ + int ret = 0; + BIGNUM *p = NULL; + BIGNUM *q = NULL; + BN_CTX *bn_ctx = NULL; + + p = BN_new(); + q = BN_new(); + bn_ctx = BN_CTX_new(); + + if (!key->n) key->n = BN_new(); + if (!key->lambda) key->lambda = BN_new(); + if (!key->n_squared) key->n_squared = BN_new(); + if (!key->n_plusone) key->n_plusone = BN_new(); + if (!key->x) key->x = BN_new(); + if (!p || !q || !bn_ctx || !key->n || !key->lambda || + !key->n_squared || !key->n_plusone || !key->x) { + goto end; + } + + key->bits = bits; + + do { + if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL)) { + PAILLIERerr(PAILLIER_F_PAILLIER_GENERATE_KEY, + PAILLIER_R_GENERATE_PRIME_FAILED); + goto end; + } + + if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL)) { + PAILLIERerr(PAILLIER_F_PAILLIER_GENERATE_KEY, + PAILLIER_R_GENERATE_PRIME_FAILED); + goto end; + } + + if (!BN_mul(key->n, p, q, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_GENERATE_KEY, ERR_R_BN_LIB); + goto end; + } + + if (!BN_sub_word(p, 1)) { + goto end; + } + if (!BN_sub_word(q, 1)) { + goto end; + } + if (!BN_mul(key->lambda, p, q, bn_ctx)) { + goto end; + } + + BN_sqr(key->n_squared, key->n, bn_ctx); + BN_copy(key->n_plusone, key->n); + BN_add_word(key->n_plusone, 1); + + /* + BN_mod_exp(key->x, key->n_plusone, key->lambda, key->n_squared, bn_ctx); + BN_sub_word(key->x, 1); + BN_div(key->x, key->x, key->n); + BN_mod_inverse(key->x, key->x, key->n, bn_ctx); + */ + + } while (0); + +end: + BN_clear_free(p); + BN_clear_free(q); + return ret; +} + +int PAILLIER_check_key(PAILLIER *key) +{ + PAILLIERerr(PAILLIER_F_PAILLIER_CHECK_KEY, PAILLIER_R_NOT_IMPLEMENTED); + return 0; +} + +int PAILLIER_encrypt(BIGNUM *c, const BIGNUM *m, PAILLIER *pub_key) +{ + int ret = 0; + BIGNUM *r = NULL; + BN_CTX *bn_ctx = NULL; + + if (BN_cmp(m, pub_key->n) >= 0) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, PAILLIER_R_INVALID_PLAINTEXT); + goto end; + } + + r = BN_new(); + bn_ctx = BN_CTX_new(); + if (!r || !bn_ctx) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + do { + if (!BN_rand_range(r, pub_key->n)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(r)); + + if (!pub_key->n_plusone) { + if (!(pub_key->n_plusone = BN_dup(pub_key->n))) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_add_word(pub_key->n_plusone, 1)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + BN_free(pub_key->n_plusone); + pub_key->n_plusone = NULL; + goto end; + } + } + + if (!pub_key->n_squared) { + if (!(pub_key->n_squared = BN_new())) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_sqr(pub_key->n_squared, pub_key->n, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + BN_free(pub_key->n_squared); + pub_key->n_squared = NULL; + goto end; + } + } + + if (!BN_mod_exp(c, pub_key->n_plusone, m, pub_key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_exp(r, r, pub_key->n, pub_key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_mul(c, c, r, pub_key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_ENCRYPT, ERR_R_BN_LIB); + goto end; + } + + ret = 1; +end: + BN_clear_free(r); + BN_CTX_free(bn_ctx); + return ret; +} + +int PAILLIER_decrypt(BIGNUM *m, const BIGNUM *c, PAILLIER *key) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + + if (!(bn_ctx = BN_CTX_new())) { + PAILLIERerr(PAILLIER_F_PAILLIER_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_exp(m, c, key->lambda, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_sub_word(m, 1)) { + PAILLIERerr(PAILLIER_F_PAILLIER_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_div(m, NULL, m, key->n, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_DECRYPT, ERR_R_BN_LIB); + goto end; + } + if (!BN_mod_mul(m, m, key->x, key->n, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_DECRYPT, ERR_R_BN_LIB); + goto end; + } + ret = 1; +end: + BN_CTX_free(bn_ctx); + return ret; +} + +int PAILLIER_ciphertext_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, PAILLIER *key) +{ + int ret = 0; + BIGNUM *k = NULL; + BN_CTX *bn_ctx = NULL; + + k = BN_new(); + bn_ctx = BN_CTX_new(); + if (!k || !bn_ctx) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD, ERR_R_BN_LIB); + goto end; + } + + do { + if (!BN_rand_range(k, key->n)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(k)); + + if (!BN_mod_exp(k, k, key->n, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_mul(r, a, b, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_mul(r, r, k, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_ADD, ERR_R_BN_LIB); + goto end; + } + + ret = 1; +end: + BN_clear_free(k); + BN_CTX_free(bn_ctx); + return ret; +} + +int PAILLIER_ciphertext_scalar_mul(BIGNUM *r, const BIGNUM *scalar, const BIGNUM *a, PAILLIER *key) +{ + int ret = 0; + BIGNUM *k = NULL; + BN_CTX *bn_ctx = NULL; + + k = BN_new(); + bn_ctx = BN_CTX_new(); + if (!k || !bn_ctx) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL, ERR_R_BN_LIB); + goto end; + } + + do { + if (!BN_rand_range(k, key->n)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL, ERR_R_BN_LIB); + goto end; + } + } while (BN_is_zero(k)); + + if (!BN_mod_exp(k, k, key->n, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_exp(r, a, scalar, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL, ERR_R_BN_LIB); + goto end; + } + + if (!BN_mod_mul(r, r, k, key->n_squared, bn_ctx)) { + PAILLIERerr(PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL, ERR_R_BN_LIB); + goto end; + } + + ret = 1; +end: + BN_clear_free(k); + BN_CTX_free(bn_ctx); + return 0; +} + diff --git a/include/openssl/err.h b/include/openssl/err.h index 812b09ca..37efb62e 100644 --- a/include/openssl/err.h +++ b/include/openssl/err.h @@ -95,6 +95,7 @@ typedef struct err_state_st { # define ERR_LIB_KDF 52 # define ERR_LIB_KDF2 53 # define ERR_LIB_FFX 54 +# define ERR_LIB_PAILLIER 55 # define ERR_LIB_USER 128 @@ -135,6 +136,7 @@ typedef struct err_state_st { # define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define KDF2err(f,r) ERR_PUT_error(ERR_LIB_KDF2,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define FFXerr(f,r) ERR_PUT_error(ERR_LIB_FFX,(f),(r),OPENSSL_FILE,OPENSSL_LINE) +# define PAILLIERerr(f,r) ERR_PUT_error(ERR_LIB_PAILLIER,(f),(r),OPENSSL_FILE,OPENSSL_LINE) # define ERR_PACK(l,f,r) ( \ (((unsigned int)(l) & 0x0FF) << 24L) | \ @@ -184,6 +186,7 @@ typedef struct err_state_st { # define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */ # define ERR_R_KDF2_LIB ERR_LIB_KDF2/* 53 */ # define ERR_R_FFX_LIB ERR_LIB_FFX/* 54 */ +# define ERR_R_PAILLIER_LIB ERR_LIB_PAILLIER/* 55 */ # define ERR_R_NESTED_ASN1_ERROR 58 # define ERR_R_MISSING_ASN1_EOS 63 diff --git a/include/openssl/paillier.h b/include/openssl/paillier.h new file mode 100644 index 00000000..130c3918 --- /dev/null +++ b/include/openssl/paillier.h @@ -0,0 +1,109 @@ +/* ==================================================================== + * Copyright (c) 2015 - 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. + * ==================================================================== + */ +/* + * Paillier's Cryptosystem + */ + +#ifndef HEADER_PAILLIER_H +#define HEADER_PAILLIER_H +#ifndef NO_GMSSL + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct paillier_st PAILLIER; + +PAILLIER *PAILLIER_new(void); +void PAILLIER_free(PAILLIER *key); + +int PAILLIER_generate_key(PAILLIER *key, int bits); +int PAILLIER_check_key(PAILLIER *key); +int PAILLIER_encrypt(BIGNUM *out, const BIGNUM *in, PAILLIER *key); +int PAILLIER_decrypt(BIGNUM *out, const BIGNUM *in, PAILLIER *key); +int PAILLIER_ciphertext_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, PAILLIER *key); +int PAILLIER_ciphertext_scalar_mul(BIGNUM *r, const BIGNUM *scalar, const BIGNUM *a, PAILLIER *key); + +DECLARE_ASN1_ENCODE_FUNCTIONS_const(PAILLIER, PAILLIER_PUBLIC_KEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(PAILLIER, PAILLIER_PRIVATE_KEY) + +/* 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_PAILLIER_strings(void); + +/* Error codes for the PAILLIER functions. */ + +/* Function codes. */ +# define PAILLIER_F_PAILLIER_CHECK_KEY 100 +# define PAILLIER_F_PAILLIER_CIPHERTEXT_ADD 101 +# define PAILLIER_F_PAILLIER_CIPHERTEXT_SCALAR_MUL 102 +# define PAILLIER_F_PAILLIER_DECRYPT 103 +# define PAILLIER_F_PAILLIER_ENCRYPT 104 +# define PAILLIER_F_PAILLIER_GENERATE_KEY 105 +# define PAILLIER_F_PAILLIER_NEW 106 + +/* Reason codes. */ +# define PAILLIER_R_GENERATE_PRIME_FAILED 100 +# define PAILLIER_R_INVALID_PLAINTEXT 101 +# define PAILLIER_R_MALLOC_FAILED 102 +# define PAILLIER_R_NOT_IMPLEMENTED 103 + +# ifdef __cplusplus +} +# endif +# endif +#endif diff --git a/test/build.info b/test/build.info index 9c812344..608d88e4 100644 --- a/test/build.info +++ b/test/build.info @@ -17,7 +17,7 @@ IF[{- !$disabled{tests} -}] dtlsv1listentest ct_test threadstest afalgtest d2i_test \ ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \ bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \ - sm3test sms4test kdf2test eciestest ffxtest + sm3test sms4test kdf2test eciestest ffxtest sm2test pailliertest SOURCE[aborttest]=aborttest.c INCLUDE[aborttest]=../include @@ -304,6 +304,14 @@ IF[{- !$disabled{tests} -}] INCLUDE[ffxtest]=../include DEPEND[ffxtest]=../libcrypto + SOURCE[sm2test]=sm2test.c + INCLUDE[sm2test]=../include + DEPEND[sm2test]=../libcrypto + + SOURCE[pailliertest]=pailliertest.c + INCLUDE[pailliertest]=../include + DEPEND[pailliertest]=../libcrypto + IF[{- !$disabled{shared} -}] PROGRAMS_NO_INST=shlibloadtest SOURCE[shlibloadtest]=shlibloadtest.c diff --git a/test/pailliertest.c b/test/pailliertest.c new file mode 100644 index 00000000..3c7233e7 --- /dev/null +++ b/test/pailliertest.c @@ -0,0 +1,184 @@ +/* ==================================================================== + * 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_PAILLIER +int main(int argc, char **argv) +{ + printf("NO PAILLIER support\n"); + return 0; +} +#else +# include +# include +# include + +static int PAILLIER_test(int verbose) +{ + int ret = 0; + int kbits = 2048; + PAILLIER *key = NULL; + BIGNUM *mx = NULL; + BIGNUM *m1 = NULL; + BIGNUM *m2 = NULL; + BIGNUM *m3 = NULL; + BIGNUM *c1 = NULL; + BIGNUM *c2 = NULL; + BIGNUM *c3 = NULL; + BN_ULONG n; + + /* generate key pair */ + if (!(key = PAILLIER_new())) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (!PAILLIER_generate_key(key, kbits)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + + /* tmp values */ + mx = BN_new(); + m1 = BN_new(); + m2 = BN_new(); + m3 = BN_new(); + c1 = BN_new(); + c2 = BN_new(); + c2 = BN_new(); + + if (!mx || !m1 || !m2 || !m3 || !c1 || !c2 || !c3) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + + /* mx is the max value of plaintext integers */ + if (!BN_set_word(mx, INT_MAX/2)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + + /* rand plaintexts */ + if (!BN_rand_range(m1, mx)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (!BN_rand_range(m2, mx)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (verbose) { + printf("m1 = "); + BN_print_fp(stdout, m1); + printf("m2 = "); + BN_print_fp(stdout, m2); + } + + /* encrypt and ciphertext addition */ + if (!PAILLIER_encrypt(c1, m1, key)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (!PAILLIER_encrypt(c2, m2, key)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (!PAILLIER_ciphertext_add(c3, c1, c2, key)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + if (!PAILLIER_decrypt(m3, c3, key)) { + fprintf(stderr, "%s %d\n", __FILE__, __LINE__); + ERR_print_errors_fp(stderr); + goto end; + } + + /* convert plaintext to scalar value */ + n = BN_get_word(m3); + + if (verbose) { + printf("m1 + m2 = %lu\n", n); + } + + ret = 1; + +end: + if (verbose) { + printf("%s %s\n", __FUNCTION__, + ret == 1 ? "passed" : "failed"); + } + PAILLIER_free(key); + BN_free(mx); + BN_free(m1); + BN_free(m2); + BN_free(m3); + BN_free(c1); + BN_free(c2); + BN_free(c3); + return ret; +} + +int main(int argc, char **argv) +{ + int err = 0; + return err; +} +#endif diff --git a/test/recipes/15-test_paillier.t b/test/recipes/15-test_paillier.t new file mode 100644 index 00000000..904d2eee --- /dev/null +++ b/test/recipes/15-test_paillier.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_paillier", "pailliertest", "paillier"); diff --git a/util/mkdef.pl b/util/mkdef.pl index aeed80cf..8d42aefd 100755 --- a/util/mkdef.pl +++ b/util/mkdef.pl @@ -132,7 +132,7 @@ my @known_algorithms = ( "RC2", "RC4", "RC5", "IDEA", "DES", "BF", "CMAC", # APPLINK (win build feature?) "APPLINK", - "SM3", "SMS4", "KDF2", "ECIES", "FFX" + "SM3", "SMS4", "KDF2", "ECIES", "FFX", "PAILLIER" ); my %disabled_algorithms;