diff --git a/crypto/cpk/cpk_lib.c b/crypto/cpk/cpk_lib.c index 50713047..dee225c6 100755 --- a/crypto/cpk/cpk_lib.c +++ b/crypto/cpk/cpk_lib.c @@ -80,6 +80,7 @@ CPK_MASTER_SECRET *CPK_MASTER_SECRET_create(const char *domain_id, BIGNUM *bn = NULL; BIGNUM *order = NULL; X509_PUBKEY *pubkey = NULL; + const X509_ALGOR *pkey_algor; int pkey_type; int i, bn_size, num_factors; unsigned char *bn_ptr; @@ -132,16 +133,13 @@ CPK_MASTER_SECRET *CPK_MASTER_SECRET_create(const char *domain_id, CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } + + X509_PUBKEY_get0_param(NULL, NULL, NULL, &pkey_algor, pubkey); X509_ALGOR_free(master->pkey_algor); - - X509_ALGOR_set0(master->pkey_algor, OBJ_nid2obj(EVP_PKEY_id(pkey)), 0, NULL); - - /* - if (!(master->pkey_algor = X509_ALGOR_dup(pubkey->algor))) { + if (!(master->pkey_algor = X509_ALGOR_dup(pkey_algor))) { CPKerr(CPK_F_CPK_MASTER_SECRET_CREATE, ERR_R_X509_LIB); goto err; } - */ //FIXME: check the validity of CPK_MAP X509_ALGOR_free(master->map_algor); @@ -202,6 +200,9 @@ CPK_PUBLIC_PARAMS *CPK_MASTER_SECRET_extract_public_params(CPK_MASTER_SECRET *ma { CPK_PUBLIC_PARAMS *param = NULL; int pkey_type; + + OPENSSL_assert(master->pkey_algor->algorithm); + pkey_type = OBJ_obj2nid(master->pkey_algor->algorithm); @@ -234,6 +235,7 @@ CPK_PUBLIC_PARAMS *CPK_MASTER_SECRET_extract_public_params(CPK_MASTER_SECRET *ma goto err; } + switch (pkey_type) { case EVP_PKEY_EC: if (!extract_ec_params(master, param)) { diff --git a/demos/cpk/cpk-keygen.c b/demos/cpk/cpk-keygen.c new file mode 100644 index 00000000..2988b97b --- /dev/null +++ b/demos/cpk/cpk-keygen.c @@ -0,0 +1,95 @@ +/* ==================================================================== + * Copyright (c) 2018 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 + +int main(int argc, char **argv) +{ + int ret = -1; + char *prog = basename(argv[0]); + BIO *msk_bio = NULL; + BIO *sk_bio = NULL; + CPK_MASTER_SECRET *msk = NULL; + EVP_PKEY *sk = NULL; + + if (argc != 4) { + printf("usage: %s \n", prog); + return 0; + } + + if (!(msk_bio = BIO_new_file(argv[1], "r")) + || !(msk = d2i_CPK_MASTER_SECRET_bio(msk_bio, NULL))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(sk = CPK_MASTER_SECRET_extract_private_key(msk, argv[2]))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(sk_bio = BIO_new_file(argv[3], "w")) + || !PEM_write_bio_PrivateKey(sk_bio, sk, NULL, NULL, 0, NULL, NULL)) { + ERR_print_errors_fp(stderr); + goto end; + } + + ret = 0; + +end: + BIO_free(msk_bio); + BIO_free(sk_bio); + CPK_MASTER_SECRET_free(msk); + EVP_PKEY_free(sk); + return ret; +} diff --git a/demos/cpk/cpk-setup.c b/demos/cpk/cpk-setup.c new file mode 100644 index 00000000..200e52b3 --- /dev/null +++ b/demos/cpk/cpk-setup.c @@ -0,0 +1,104 @@ +/* ==================================================================== + * Copyright (c) 2018 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 + + +int main(int argc, char **argv) +{ + int ret = -1; + char *prog = basename(argv[0]); + X509_ALGOR *map = NULL; + EC_KEY *ec_key = NULL; + EVP_PKEY *pkey = NULL; + CPK_MASTER_SECRET *msk = NULL; + CPK_PUBLIC_PARAMS *mpk = NULL; + BIO *mpk_bio = NULL; + BIO *msk_bio = NULL; + + if (argc != 3) { + printf("usage: %s \n", prog); + return 0; + } + + if (!(map = CPK_MAP_new_default()) + || !(ec_key = EC_KEY_new_by_curve_name(NID_sm2p256v1)) + || !EC_KEY_generate_key(ec_key) + || !(pkey = EVP_PKEY_new()) + || !EVP_PKEY_set1_EC_KEY(pkey, ec_key) + || !(msk = CPK_MASTER_SECRET_create("codesign", pkey, map)) + || !(mpk = CPK_MASTER_SECRET_extract_public_params(msk))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(mpk_bio = BIO_new_file(argv[1], "w")) + || !(msk_bio = BIO_new_file(argv[2], "w")) + || !i2d_CPK_MASTER_SECRET_bio(msk_bio, msk) + || !i2d_CPK_PUBLIC_PARAMS_bio(mpk_bio, mpk)) { + ERR_print_errors_fp(stderr); + goto end; + } + + ret = 0; + +end: + X509_ALGOR_free(map); + //EC_KEY_free(ec_key); + EVP_PKEY_free(pkey); + CPK_MASTER_SECRET_free(msk); + CPK_PUBLIC_PARAMS_free(mpk); + BIO_free(msk_bio); + BIO_free(mpk_bio); + return ret; +} diff --git a/demos/cpk/cpk-sign.c b/demos/cpk/cpk-sign.c new file mode 100644 index 00000000..01189259 --- /dev/null +++ b/demos/cpk/cpk-sign.c @@ -0,0 +1,141 @@ +/* ==================================================================== + * Copyright (c) 2018 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 + +int main(int argc, char **argv) +{ + int ret = -1; + char *prog = basename(argv[0]); + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *sk = NULL; + unsigned char magic[] = "~CPK signature appended~"; + unsigned char sig[128] = {0}; + size_t sigsize = sizeof(sig); + unsigned int idlen, siglen, totallen; + BIO *in_bio = NULL; + BIO *sk_bio = NULL; + BIO *out_bio = NULL; + unsigned char buf[1024]; + int len; + + if (argc != 5) { + printf("usage: %s \n", prog); + return 0; + } + + if (strlen(argv[2]) > 64) { + fprintf(stderr, "%s: signer's id too long\n", prog); + goto end; + } + + if (!(in_bio = BIO_new_file(argv[1], "r")) + || !(sk_bio = BIO_new_file(argv[3], "r")) + || !(out_bio = BIO_new_file(argv[4], "w"))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(sk = PEM_read_bio_PrivateKey(sk_bio, NULL, NULL, NULL))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(md_ctx = EVP_MD_CTX_new())) { + ERR_print_errors_fp(stderr); + goto end; + } + if (!EVP_DigestSignInit(md_ctx, &pctx, EVP_sm3(), NULL, sk)) { + ERR_print_errors_fp(stderr); + goto end; + } + while ((len = BIO_read(in_bio, buf, sizeof(buf))) > 0) { + if (!EVP_DigestSignUpdate(md_ctx, buf, len)) { + ERR_print_errors_fp(stderr); + goto end; + } + if (len != BIO_write(out_bio, buf, len)) { + ERR_print_errors_fp(stderr); + goto end; + } + } + if (!EVP_DigestSignFinal(md_ctx, sig, &sigsize)) { + ERR_print_errors_fp(stderr); + goto end; + } + + idlen = strlen(argv[2]); + siglen = (unsigned int)sigsize; + totallen = sizeof(idlen) + idlen + sizeof(siglen) + siglen; + + if (BIO_write(out_bio, &idlen, sizeof(idlen)) != sizeof(idlen) + || BIO_write(out_bio, argv[2], strlen(argv[2])) != strlen(argv[2]) + || BIO_write(out_bio, &siglen, sizeof(siglen)) != sizeof(siglen) + || BIO_write(out_bio, sig, siglen) != siglen + || BIO_write(out_bio, &totallen, sizeof(totallen)) != sizeof(totallen) + || BIO_write(out_bio, magic, sizeof(magic)) != sizeof(magic)) { + ERR_print_errors_fp(stderr); + goto end; + } + + ret = 0; + +end: + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_free(sk); + BIO_free(in_bio); + BIO_free(sk_bio); + BIO_free(out_bio); + return ret; +} diff --git a/demos/cpk/cpk-verify.c b/demos/cpk/cpk-verify.c new file mode 100644 index 00000000..53b403a1 --- /dev/null +++ b/demos/cpk/cpk-verify.c @@ -0,0 +1,189 @@ +/* ==================================================================== + * Copyright (c) 2018 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 + +int main(int argc, char **argv) +{ + int ret = -1; + char *prog = basename(argv[0]); + FILE *fp = NULL; + BIO *bio = NULL; + BIO *bio_mpk = NULL; + CPK_PUBLIC_PARAMS *mpk = NULL; + EVP_PKEY *pk = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx; + unsigned char magicstr[] = "~CPK signature appended~"; + unsigned char magic[sizeof(magicstr)] = {0}; + unsigned char id[128]; + unsigned char sig[128]; + unsigned int idlen, siglen, totallen; + int datalen; + + if (argc != 3) { + printf("usage: %s \n", prog); + return 0; + } + + if (!(fp = fopen(argv[1], "r"))) { + fprintf(stderr, "%s: open file failed\n", prog); + goto end; + } + + if (fseek(fp, -(sizeof(magic) + sizeof(unsigned int)), SEEK_END) != 0) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + if ((datalen = ftell(fp)) <= 0) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + if (fread(&totallen, sizeof(unsigned int), 1, fp) != sizeof(unsigned char)) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + datalen -= totallen; + + if (fread(magic, 1, sizeof(magic), fp) != sizeof(magic)) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + if (memcmp(magic, magicstr, sizeof(magic)) != 0) { + fprintf(stderr, "%s: file is not signed\n", prog); + goto end; + } + + if (fseek(fp, datalen, SEEK_SET) != 0) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + if (fread(&idlen, 1, 4, fp) != 4) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + if (fread(id, 1, idlen, fp) != idlen) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + if (fread(&siglen, 1, sizeof(unsigned int), fp) != sizeof(unsigned int)) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + if (fread(sig, 1, siglen, fp) != siglen) { + fprintf(stderr, "%s: parse file error\n", prog); + goto end; + } + + fclose(fp); + fp = NULL; + + if (!(bio = BIO_new_file(argv[1], "r")) + || !(bio_mpk = BIO_new_file(argv[2], "r"))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(mpk = d2i_CPK_PUBLIC_PARAMS_bio(bio_mpk, NULL))) { + ERR_print_errors_fp(stderr); + goto end; + } + if (!(pk = CPK_PUBLIC_PARAMS_extract_public_key(mpk, (char *)id))) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!(md_ctx = EVP_MD_CTX_new())) { + ERR_print_errors_fp(stderr); + goto end; + } + if (!EVP_DigestVerifyInit(md_ctx, &pctx, EVP_sm3(), NULL, pk)) { + ERR_print_errors_fp(stderr); + goto end; + } + + while (datalen > 0) { + unsigned char buf[1024]; + int len; + + len = sizeof(buf) < datalen ? sizeof(buf) : datalen; + + if (len != BIO_read(bio, buf, len)) { + ERR_print_errors_fp(stderr); + goto end; + } + + if (!EVP_DigestVerifyUpdate(md_ctx, buf, len)) { + ERR_print_errors_fp(stderr); + goto end; + } + + datalen -= len; + } + + if (1 != EVP_DigestVerifyFinal(md_ctx, sig, siglen)) { + ERR_print_errors_fp(stderr); + printf("%s: failed\n", argv[1]); + goto end; + } + printf("%s: success\n", argv[1]); + + + ret = 0; +end: + return ret; +}