static int test_EVP_SM2_verify(void) { /* From https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02#appendix-A */ const char *pubkey = "-----BEGIN PUBLIC KEY-----\n" "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEAhULWnkwETxjouSQ1\n" "v2/33kVyg5FcRVF9ci7biwjx38MwRAQgeHlotPoyw/0kF4Quc7v+/y88hItoMdfg\n" "7GUiizk35JgEIGPkxtOyOwyEnPhCQUhL/kj2HVmlsWugbm4S0donxSSaBEEEQh3r\n" "1hti6rZ0ZDTrw8wxXjIiCzut1QvcTE5sFH/t1D0GgFEry7QsB9RzSdIVO3DE5df9\n" "/L+jbqGoWEG55G4JogIhAIVC1p5MBE8Y6LkkNb9v990pdyBjBIVijVrnTufDLnm3\n" "AgEBA0IABArkx3mKoPEZRxvuEYJb5GICu3nipYRElel8BP9N8lSKfAJA+I8c1OFj\n" "Uqc8F7fxbwc1PlOhdtaEqf4Ma7eY6Fc=\n" "-----END PUBLIC KEY-----\n"; const char *msg = "message digest"; const char *id = "*****@*****.**"; const uint8_t signature[] = { 0x30, 0x44, 0x02, 0x20, 0x40, 0xF1, 0xEC, 0x59, 0xF7, 0x93, 0xD9, 0xF4, 0x9E, 0x09, 0xDC, 0xEF, 0x49, 0x13, 0x0D, 0x41, 0x94, 0xF7, 0x9F, 0xB1, 0xEE, 0xD2, 0xCA, 0xA5, 0x5B, 0xAC, 0xDB, 0x49, 0xC4, 0xE7, 0x55, 0xD1, 0x02, 0x20, 0x6F, 0xC6, 0xDA, 0xC3, 0x2C, 0x5D, 0x5C, 0xF1, 0x0C, 0x77, 0xDF, 0xB2, 0x0F, 0x7C, 0x2E, 0xB6, 0x67, 0xA4, 0x57, 0x87, 0x2F, 0xB0, 0x9E, 0xC5, 0x63, 0x27, 0xA6, 0x7E, 0xC7, 0xDE, 0xEB, 0xE7 }; int rc = 0; BIO *bio = NULL; EVP_PKEY *pkey = NULL; EVP_MD_CTX *mctx = NULL; EVP_PKEY_CTX *pctx = NULL; bio = BIO_new_mem_buf(pubkey, strlen(pubkey)); if (!TEST_true(bio != NULL)) goto done; pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); if (!TEST_true(pkey != NULL)) goto done; if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) goto done; if (!TEST_ptr(mctx = EVP_MD_CTX_new())) goto done; if (!TEST_ptr(pctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, (const uint8_t *)id, strlen(id)), 0)) goto done; EVP_MD_CTX_set_pkey_ctx(mctx, pctx); if (!TEST_true(EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey))) goto done; if (!TEST_true(EVP_DigestVerifyUpdate(mctx, msg, strlen(msg)))) goto done; if (!TEST_true(EVP_DigestVerifyFinal(mctx, signature, sizeof(signature)))) goto done; rc = 1; done: BIO_free(bio); EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(pctx); EVP_MD_CTX_free(mctx); return rc; }
static int test_EVP_SM2(void) { int ret = 0; EVP_PKEY *pkey = NULL; EVP_PKEY *params = NULL; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY_CTX *kctx = NULL; EVP_PKEY_CTX *sctx = NULL; size_t sig_len = 0; unsigned char *sig = NULL; EVP_MD_CTX *md_ctx = NULL; EVP_MD_CTX *md_ctx_verify = NULL; EVP_PKEY_CTX *cctx = NULL; uint8_t ciphertext[128]; size_t ctext_len = sizeof(ciphertext); uint8_t plaintext[8]; size_t ptext_len = sizeof(plaintext); uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'}; pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); if (!TEST_ptr(pctx)) goto done; if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1)) goto done; if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2))) goto done; if (!TEST_true(EVP_PKEY_paramgen(pctx, ¶ms))) goto done; kctx = EVP_PKEY_CTX_new(params, NULL); if (!TEST_ptr(kctx)) goto done; if (!TEST_true(EVP_PKEY_keygen_init(kctx))) goto done; if (!TEST_true(EVP_PKEY_keygen(kctx, &pkey))) goto done; if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) goto done; if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())) goto done; if (!TEST_ptr(md_ctx_verify = EVP_MD_CTX_new())) goto done; if (!TEST_ptr(sctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx); if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) goto done; if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) goto done; if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) goto done; /* Determine the size of the signature. */ if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))) goto done; if (!TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey))) goto done; if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))) goto done; if (!TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len))) goto done; /* Ensure that the signature round-trips. */ if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey))) goto done; if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg)))) goto done; if (!TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len))) goto done; /* now check encryption/decryption */ if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; if (!TEST_true(EVP_PKEY_encrypt_init(cctx))) goto done; if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg)))) goto done; if (!TEST_true(EVP_PKEY_decrypt_init(cctx))) goto done; if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len))) goto done; if (!TEST_true(ptext_len == sizeof(kMsg))) goto done; if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0)) goto done; ret = 1; done: EVP_PKEY_CTX_free(pctx); EVP_PKEY_CTX_free(kctx); EVP_PKEY_CTX_free(sctx); EVP_PKEY_CTX_free(cctx); EVP_PKEY_free(pkey); EVP_PKEY_free(params); EVP_MD_CTX_free(md_ctx); EVP_MD_CTX_free(md_ctx_verify); OPENSSL_free(sig); return ret; }
static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, const char *keyfile, int keyform, int key_type, char *passinarg, int pkey_op, ENGINE *e, const int engine_impl, EVP_PKEY **ppkey) { EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; ENGINE *impl = NULL; char *passin = NULL; int rv = -1; X509 *x; if (((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) || (pkey_op == EVP_PKEY_OP_DERIVE)) && (key_type != KEY_PRIVKEY && kdfalg == NULL)) { BIO_printf(bio_err, "A private key is needed for this operation\n"); goto end; } if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); goto end; } switch (key_type) { case KEY_PRIVKEY: pkey = load_key(keyfile, keyform, 0, passin, e, "Private Key"); break; case KEY_PUBKEY: pkey = load_pubkey(keyfile, keyform, 0, NULL, e, "Public Key"); break; case KEY_CERT: x = load_cert(keyfile, keyform, "Certificate"); if (x) { pkey = X509_get_pubkey(x); X509_free(x); } break; case KEY_NONE: break; } #ifndef OPENSSL_NO_ENGINE if (engine_impl) impl = e; #endif if (kdfalg != NULL) { int kdfnid = OBJ_sn2nid(kdfalg); if (kdfnid == NID_undef) { kdfnid = OBJ_ln2nid(kdfalg); if (kdfnid == NID_undef) { BIO_printf(bio_err, "The given KDF \"%s\" is unknown.\n", kdfalg); goto end; } } ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); } else { EC_KEY *eckey = NULL; const EC_GROUP *group = NULL; int nid; if (pkey == NULL) goto end; /* SM2 needs a special treatment */ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (nid = EC_GROUP_get_curve_name(group)) == 0) goto end; if (nid == NID_sm2) EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); } *pkeysize = EVP_PKEY_size(pkey); ctx = EVP_PKEY_CTX_new(pkey, impl); if (ppkey != NULL) *ppkey = pkey; EVP_PKEY_free(pkey); } if (ctx == NULL) goto end; switch (pkey_op) { case EVP_PKEY_OP_SIGN: rv = EVP_PKEY_sign_init(ctx); break; case EVP_PKEY_OP_VERIFY: rv = EVP_PKEY_verify_init(ctx); break; case EVP_PKEY_OP_VERIFYRECOVER: rv = EVP_PKEY_verify_recover_init(ctx); break; case EVP_PKEY_OP_ENCRYPT: rv = EVP_PKEY_encrypt_init(ctx); break; case EVP_PKEY_OP_DECRYPT: rv = EVP_PKEY_decrypt_init(ctx); break; case EVP_PKEY_OP_DERIVE: rv = EVP_PKEY_derive_init(ctx); break; } if (rv <= 0) { EVP_PKEY_CTX_free(ctx); ctx = NULL; } end: OPENSSL_free(passin); return ctx; }