int fips_pkey_signature_test(int id, EVP_PKEY *pkey, const unsigned char *tbs, size_t tbslen, const unsigned char *kat, size_t katlen, const EVP_MD *digest, int pad_mode, const char *fail_str) { int subid; void *ex = NULL; int ret = 0; unsigned char *sig = NULL; unsigned int siglen; static const unsigned char str1[]="12345678901234567890"; DSA_SIG *dsig = NULL; ECDSA_SIG *esig = NULL; EVP_MD_CTX mctx; FIPS_md_ctx_init(&mctx); if (tbs == NULL) tbs = str1; if (tbslen == 0) tbslen = strlen((char *)tbs); if (digest == NULL) digest = EVP_sha256(); subid = M_EVP_MD_type(digest); if (!fips_post_started(id, subid, pkey)) return 1; if (!pkey || pkey->type == EVP_PKEY_RSA) { size_t sigsize; if (!pkey) sigsize = EVP_MAX_MD_SIZE; else sigsize = RSA_size(pkey->pkey.rsa); sig = OPENSSL_malloc(sigsize); if (!sig) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,ERR_R_MALLOC_FAILURE); goto error; } } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (!fips_post_corrupt(id, subid, pkey)) { if (!FIPS_digestupdate(&mctx, tbs, 1)) goto error; } if (pkey == NULL) { if (!FIPS_digestfinal(&mctx, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_RSA) { if (!FIPS_rsa_sign_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, &siglen)) goto error; } else if (pkey->type == EVP_PKEY_DSA) { dsig = FIPS_dsa_sign_ctx(pkey->pkey.dsa, &mctx); if (!dsig) goto error; } else if (pkey->type == EVP_PKEY_EC) { esig = FIPS_ecdsa_sign_ctx(pkey->pkey.ec, &mctx); if (!esig) goto error; } if (kat && ((siglen != katlen) || memcmp(kat, sig, katlen))) goto error; #if 0 { /* Debug code to print out self test KAT discrepancies */ unsigned int i; fprintf(stderr, "%s=", fail_str); for (i = 0; i < siglen; i++) fprintf(stderr, "%02X", sig[i]); fprintf(stderr, "\n"); goto error; } #endif /* If just digest test we've finished */ if (pkey == NULL) { ret = 1; /* Well actually sucess as we've set ret to 1 */ goto error; } if (!FIPS_digestinit(&mctx, digest)) goto error; if (!FIPS_digestupdate(&mctx, tbs, tbslen)) goto error; if (pkey->type == EVP_PKEY_RSA) { ret = FIPS_rsa_verify_ctx(pkey->pkey.rsa, &mctx, pad_mode, 0, NULL, sig, siglen); } else if (pkey->type == EVP_PKEY_DSA) { ret = FIPS_dsa_verify_ctx(pkey->pkey.dsa, &mctx, dsig); } else if (pkey->type == EVP_PKEY_EC) { ret = FIPS_ecdsa_verify_ctx(pkey->pkey.ec, &mctx, esig); } error: if (dsig != NULL) FIPS_dsa_sig_free(dsig); if (esig != NULL) FIPS_ecdsa_sig_free(esig); if (sig) OPENSSL_free(sig); FIPS_md_ctx_cleanup(&mctx); if (ret != 1) { FIPSerr(FIPS_F_FIPS_PKEY_SIGNATURE_TEST,FIPS_R_TEST_FAILURE); if (fail_str) FIPS_add_error_data(2, "Type=", fail_str); fips_post_failed(id, subid, ex); return 0; } return fips_post_success(id, subid, pkey); }
jint Java_org_keysupport_provider_ECDSASignature_jniVerifyFinal(JNIEnv *env, jobject obj, jbyteArray jmsg, jint jmdid, jbyteArray jsig) { // LOGD("entering ECDSASignature_jniVerifyFinal"); EC_Ctx *ec; EVP_MD_CTX *ctx = 0; const EVP_MD *md; jsize msgLen = 0; jsize sigLen = 0; const unsigned char *sig_ptr = NULL; if (!(ec = get_ptr(env, obj))) { LOGE("Failed to obtain key pointer"); return 0; } if (!(ctx = (EVP_MD_CTX *) malloc(sizeof(EVP_MD_CTX)))) { throw_exception(env, "java/lang/RuntimeException", "allocating EVP_MD_CTX"); destroy_ec_ctx(ec); FIPS_md_ctx_destroy(ctx); return 0; } md = FIPS_get_digestbynid(jmdid); ctx = EVP_MD_CTX_create(); msgLen = (*env)->GetArrayLength(env, jmsg); sigLen = (*env)->GetArrayLength(env, jsig); jbyte msg[msgLen]; jbyte sig[sigLen]; (*env)->GetByteArrayRegion(env, jmsg, 0, msgLen, msg); (*env)->GetByteArrayRegion(env, jsig, 0, sigLen, sig); sig_ptr = sig; ECDSA_SIG *esig = d2i_ECDSA_SIG(NULL, &sig_ptr, sigLen); FIPS_digestinit(ctx, md); int ok = FIPS_ecdsa_verify(ec->ec, msg, msgLen, md, esig); /* * This is handled a bit differently than the way OpenSSL * handles RSA Signatures, so our error handling below is a bit different. * * returns * 1: correct signature * 0: incorrect signature * -1: error */ // LOGD("FIPS_ecdsa_verify Returned: %d\n", ok); FIPS_md_ctx_destroy(ctx); FIPS_ecdsa_sig_free(esig); if (ok == 0) { throw_exception(env, "java/security/SignatureException", "Bad Signature"); return 0; } else if (ok == -1) { /* * TODO: Print any pending errors * ERR_print_errors_fp(ANDROID_LOG_ERROR); */ ERR_load_crypto_strings(); LOGE("%s", ERR_error_string(ERR_peek_error(), NULL)); throw_exception(env, "java/security/SignatureException", "jniVerifyFinal fail"); ERR_free_strings(); return 0; } // LOGD("leaving ECDSASignature_jniVerifyFinal"); return ok; }
static int SigGen(FILE *in, FILE *out) { char buf[2048], lbuf[2048]; char *keyword, *value; unsigned char *msg; int curve_nid = NID_undef; long mlen; BIGNUM *Qx = NULL, *Qy = NULL; EC_KEY *key = NULL; ECDSA_SIG *sig = NULL; const EVP_MD *digest = NULL; Qx = BN_new(); Qy = BN_new(); while (fgets(buf, sizeof buf, in) != NULL) { fputs(buf, out); if (*buf == '[') { curve_nid = elookup_curve(buf, lbuf, &digest); if (curve_nid == NID_undef) return 0; } if (!parse_line(&keyword, &value, lbuf, buf)) continue; if (!strcmp(keyword, "Msg")) { msg = hex2bin_m(value, &mlen); if (!msg) { fprintf(stderr, "Invalid Message\n"); return 0; } key = EC_KEY_new_by_curve_name(curve_nid); if (!EC_KEY_generate_key(key)) { fprintf(stderr, "Error generating key\n"); return 0; } if (!ec_get_pubkey(key, Qx, Qy)) { fprintf(stderr, "Error getting public key\n"); return 0; } sig = FIPS_ecdsa_sign(key, msg, mlen, digest); if (!sig) { fprintf(stderr, "Error signing message\n"); return 0; } do_bn_print_name(out, "Qx", Qx); do_bn_print_name(out, "Qy", Qy); do_bn_print_name(out, "R", sig->r); do_bn_print_name(out, "S", sig->s); EC_KEY_free(key); OPENSSL_free(msg); FIPS_ecdsa_sig_free(sig); } } BN_free(Qx); BN_free(Qy); return 1; }