// #ifdef USE_REAL_HEADERS #include #include #include #include /* ============================================================================= * UTILITY FUNCTIONS - Common operations shared across signature APIs * ============================================================================= */ /** * Create message digest from raw message data */ static int create_digest(const unsigned char *message, size_t message_len, const EVP_MD *md, unsigned char *digest, unsigned int *digest_len) { EVP_MD_CTX *md_ctx = EVP_MD_CTX_new(); int ret = 0; if (!md_ctx || EVP_DigestInit_ex(md_ctx, md, NULL) != 1 || EVP_DigestUpdate(md_ctx, message, message_len) != 1 || EVP_DigestFinal_ex(md_ctx, digest, digest_len) != 1) { goto cleanup; } ret = 1; cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /** * Allocate signature buffer with appropriate size */ static unsigned char* allocate_signature_buffer(size_t *sig_len, const EVP_PKEY *pkey) { *sig_len = EVP_PKEY_size(pkey); return OPENSSL_malloc(*sig_len); } /* ============================================================================= * EVP_SIGN/VERIFY API - Legacy high-level API (older, simpler) * ============================================================================= */ /** * Sign message using EVP_Sign API (legacy) * Simple API with built-in hashing and signing */ int sign_using_evp_sign(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; unsigned int sig_len = 0; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_SignInit(md_ctx, md) != 1 || EVP_SignUpdate(md_ctx, message, message_len) != 1) { goto cleanup; } // more updates EVP_SignUpdate(md_ctx, message+1, message_len-1); *signature = allocate_signature_buffer(signature_len, pkey); if (!*signature) goto cleanup; if (EVP_SignFinal(md_ctx, *signature, &sig_len, pkey) == 1) { *signature_len = sig_len; ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /** * Verify signature using EVP_Verify API (legacy) * Simple API with built-in hashing and verification */ int verify_using_evp_verify(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_VerifyInit(md_ctx, md) != 1 || EVP_VerifyUpdate(md_ctx, message, message_len) != 1 || EVP_VerifyUpdate(md_ctx, message+1, message_len-1) != 1 || EVP_VerifyFinal(md_ctx, signature, (unsigned int)signature_len, pkey) != 1) { goto cleanup; } ret = 1; cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /* ============================================================================= * EVP_DIGESTSIGN/DIGESTVERIFY API - Modern recommended API * ============================================================================= */ /** * Sign message using EVP_DigestSign API (recommended) * Modern flexible API with better algorithm support */ int sign_using_evp_digestsign(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey) != 1 || EVP_DigestSignUpdate(md_ctx, message, message_len) != 1 || EVP_DigestSignFinal(md_ctx, NULL, signature_len) != 1) { goto cleanup; } *signature = OPENSSL_malloc(*signature_len); if (!*signature) goto cleanup; if (EVP_DigestSignFinal(md_ctx, *signature, signature_len) == 1) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /** * Verify signature using EVP_DigestVerify API (recommended) * Modern flexible API with better algorithm support */ int verify_using_evp_digestverify(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_DigestVerifyInit(md_ctx, NULL, md, NULL, pkey) != 1 || EVP_DigestVerifyUpdate(md_ctx, message, message_len) != 1 || EVP_DigestVerifyFinal(md_ctx, signature, signature_len) != 1) { goto cleanup; } ret = 1; cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /** * Sign with explicit PKEY_CTX for fine-grained parameter control * Allows custom parameter settings (e.g., padding, salt length) */ int sign_using_digestsign_with_ctx(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; EVP_PKEY_CTX *pkey_ctx = NULL; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) { goto cleanup; } EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); if (EVP_DigestSignUpdate(md_ctx, message, message_len) != 1 || EVP_DigestSignFinal(md_ctx, NULL, signature_len) != 1) { goto cleanup; } *signature = OPENSSL_malloc(*signature_len); if (!*signature) goto cleanup; if (EVP_DigestSignFinal(md_ctx, *signature, signature_len) == 1) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /** * Verify with explicit PKEY_CTX for fine-grained parameter control */ int verify_using_digestverify_with_ctx(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_MD_CTX *md_ctx = NULL; EVP_PKEY_CTX *pkey_ctx = NULL; int ret = 0; if (!(md_ctx = EVP_MD_CTX_new()) || EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1) { goto cleanup; } EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); if (EVP_DigestVerifyUpdate(md_ctx, message, message_len) != 1 || EVP_DigestVerifyFinal(md_ctx, signature, signature_len) != 1) { goto cleanup; } ret = 1; cleanup: EVP_MD_CTX_free(md_ctx); return ret; } /* ============================================================================= * EVP_PKEY_SIGN/VERIFY API - Lower level API with pre-hashed input * ============================================================================= */ /** * Sign pre-hashed digest using EVP_PKEY_sign API * Lower-level API requiring pre-computed digest */ int sign_using_evp_pkey_sign(const unsigned char *digest, size_t digest_len, unsigned char **signature, size_t *signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_PKEY_CTX *pkey_ctx = NULL; int ret = 0; if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) || EVP_PKEY_sign_init(pkey_ctx) != 1 || EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) != 1 || EVP_PKEY_sign(pkey_ctx, NULL, signature_len, digest, digest_len) != 1) { goto cleanup; } *signature = OPENSSL_malloc(*signature_len); if (!*signature) goto cleanup; if (EVP_PKEY_sign(pkey_ctx, *signature, signature_len, digest, digest_len) == 1) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: EVP_PKEY_CTX_free(pkey_ctx); return ret; } /** * Verify pre-hashed digest using EVP_PKEY_verify API * Lower-level API requiring pre-computed digest */ int verify_using_evp_pkey_verify(const unsigned char *digest, size_t digest_len, const unsigned char *signature, size_t signature_len, EVP_PKEY *pkey, const EVP_MD *md) { EVP_PKEY_CTX *pkey_ctx = NULL; int ret = 0; if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) || EVP_PKEY_verify_init(pkey_ctx) != 1 || EVP_PKEY_CTX_set_signature_md(pkey_ctx, md) != 1 || EVP_PKEY_verify(pkey_ctx, signature, signature_len, digest, digest_len) != 1) { goto cleanup; } ret = 1; cleanup: EVP_PKEY_CTX_free(pkey_ctx); return ret; } /* ============================================================================= * EVP_PKEY_SIGN_MESSAGE API - Streamlined message signing * ============================================================================= */ /** * Sign message using EVP_PKEY_sign_message API * Streamlined interface for direct message signing */ int sign_using_evp_pkey_sign_message(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, EVP_PKEY *pkey, const char *alg_name) { EVP_PKEY_CTX *pkey_ctx = NULL; EVP_SIGNATURE *alg = NULL; int ret = 0; if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup; alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL); if (EVP_PKEY_sign_message_init(pkey_ctx, alg, NULL) != 1 || EVP_PKEY_sign_message_update(pkey_ctx, message, message_len) != 1 || EVP_PKEY_sign_message_final(pkey_ctx, NULL, signature_len) != 1) { goto cleanup; } *signature = OPENSSL_malloc(*signature_len); if (!*signature) goto cleanup; if (EVP_PKEY_sign_message_final(pkey_ctx, *signature, signature_len) == 1) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: EVP_PKEY_CTX_free(pkey_ctx); return ret; } /** * Verify message using EVP_PKEY_verify_message API * Streamlined interface for direct message verification */ int verify_using_evp_pkey_verify_message(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, EVP_PKEY *pkey, const char *alg_name) { EVP_PKEY_CTX *pkey_ctx = NULL; EVP_SIGNATURE *alg = NULL; int ret = 0; if (!(pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL))) goto cleanup; alg = EVP_SIGNATURE_fetch(NULL, alg_name, NULL); if (EVP_PKEY_verify_message_init(pkey_ctx, alg, NULL) != 1) goto cleanup; EVP_PKEY_CTX_set_signature(pkey_ctx, signature, signature_len); if (EVP_PKEY_verify_message_update(pkey_ctx, message, message_len) != 1 || EVP_PKEY_verify_message_final(pkey_ctx) != 1) { goto cleanup; } ret = 1; cleanup: EVP_PKEY_CTX_free(pkey_ctx); return ret; } // /* ============================================================================= // * LOW-LEVEL RSA API - Algorithm-specific functions (deprecated) // * ============================================================================= // */ /** * Sign using low-level RSA_sign API (deprecated, RSA-only) * Direct RSA signing with manual digest computation */ int sign_using_rsa_sign(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, RSA *rsa_key, int hash_nid) { int ret = 0; *signature_len = RSA_size(rsa_key); *signature = OPENSSL_malloc(*signature_len); if (!*signature) return 0; if (RSA_sign(hash_nid, message, message_len, *signature, (unsigned int*)signature_len, rsa_key) == 1) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } return ret; } /** * Verify using low-level RSA_verify API (deprecated, RSA-only) * Direct RSA verification with manual digest computation */ int verify_using_rsa_verify(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, RSA *rsa_key, int hash_nid) { return RSA_verify(hash_nid, message, message_len, signature, (unsigned int)signature_len, rsa_key); } // /* ============================================================================= // * LOW-LEVEL DSA API - Algorithm-specific functions (deprecated) // * ============================================================================= // */ /** * Sign using low-level DSA_do_sign API (deprecated, DSA-only) * Direct DSA signing with manual digest and signature encoding */ int sign_using_dsa_sign(const unsigned char *message, size_t message_len, unsigned char **signature, size_t *signature_len, DSA *dsa_key, const EVP_MD *md) { unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; DSA_SIG *sig = NULL; const BIGNUM *r = NULL, *s = NULL; unsigned int bn_len; int ret = 0; if (!create_digest(message, message_len, md, digest, &digest_len)) return 0; sig = DSA_do_sign(digest, digest_len, dsa_key); if (!sig) return 0; DSA_SIG_get0(sig, &r, &s); if (!r || !s) goto cleanup; bn_len = DSA_size(dsa_key) / 2; *signature_len = DSA_size(dsa_key); *signature = OPENSSL_malloc(*signature_len); if (!*signature) goto cleanup; memset(*signature, 0, *signature_len); if (BN_bn2bin(r, *signature + (bn_len - BN_num_bytes(r))) > 0 && BN_bn2bin(s, *signature + bn_len + (bn_len - BN_num_bytes(s))) > 0) { ret = 1; } else { OPENSSL_free(*signature); *signature = NULL; } cleanup: DSA_SIG_free(sig); return ret; } /** * Verify using low-level DSA_do_verify API (deprecated, DSA-only) * Direct DSA verification with manual digest and signature decoding */ int verify_using_dsa_verify(const unsigned char *message, size_t message_len, const unsigned char *signature, size_t signature_len, DSA *dsa_key, const EVP_MD *md) { unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; DSA_SIG *sig = NULL; BIGNUM *r = NULL, *s = NULL; unsigned int bn_len; int ret = 0; if (!create_digest(message, message_len, md, digest, &digest_len)) return 0; sig = DSA_SIG_new(); if (!sig) return 0; r = BN_new(); s = BN_new(); if (!r || !s) goto cleanup; bn_len = DSA_size(dsa_key) / 2; if (BN_bin2bn(signature, bn_len, r) && BN_bin2bn(signature + bn_len, bn_len, s) && DSA_SIG_set0(sig, r, s) == 1) { /* r and s are now owned by sig */ r = s = NULL; ret = DSA_do_verify(digest, digest_len, sig, dsa_key); } cleanup: DSA_SIG_free(sig); BN_free(r); BN_free(s); return (ret == 1); } /* ============================================================================= * PARAMETER SETTERS - Helper functions for algorithm configuration * ============================================================================= */ /* ============================================================================= * KEY GENERATION HELPERS * ============================================================================= */ /** * Generate RSA key pair for testing */ static EVP_PKEY* generate_rsa_key(void) { EVP_PKEY_CTX *key_ctx = NULL; EVP_PKEY *key = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); return key; } /** * Generate DSA key pair for testing */ static EVP_PKEY* generate_dsa_key(void) { EVP_PKEY_CTX *param_ctx = NULL, *key_ctx = NULL; EVP_PKEY *params = NULL, *key = NULL; /* Generate parameters first */ param_ctx = EVP_PKEY_CTX_new_from_name(NULL, "dsa", NULL); if (!param_ctx) return NULL; if (EVP_PKEY_paramgen_init(param_ctx) <= 0 || EVP_PKEY_CTX_set_dsa_paramgen_bits(param_ctx, 2048) <= 0 || EVP_PKEY_paramgen(param_ctx, ¶ms) <= 0) { goto cleanup; } /* Generate key using parameters */ key_ctx = EVP_PKEY_CTX_new(params, NULL); if (!key_ctx || EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } cleanup: EVP_PKEY_CTX_free(param_ctx); EVP_PKEY_CTX_free(key_ctx); EVP_PKEY_free(params); return key; } /* ============================================================================= * TEST FUNCTIONS - Comprehensive API testing * ============================================================================= */ int testLowLevelRSASignAndVerify(){ EVP_PKEY *key = NULL; RSA *rsa_key = NULL; const unsigned char message[] = "testLowLevelRSASignAndVerify message"; const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; rsa_key = EVP_PKEY_get1_RSA(key); if (!rsa_key) { EVP_PKEY_free(key); success = 0; } if (sign_using_rsa_sign(message, message_len, &sig, &sig_len, rsa_key, NID_sha256) && verify_using_rsa_verify(message, message_len, sig, sig_len, rsa_key, NID_sha256)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } /* Cleanup */ OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testLowLevelDSASignAndVerify(){ EVP_PKEY *key = NULL; DSA *dsa_key = NULL; const unsigned char message[] = "testLowLevelDSASignAndVerify message"; const EVP_MD *md = EVP_sha256(); int success = 1; EVP_PKEY_CTX *param_ctx = NULL, *key_ctx = NULL; EVP_PKEY *params = NULL; const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; key = generate_dsa_key(); dsa_key = EVP_PKEY_get1_DSA(key); if (!dsa_key) { EVP_PKEY_free(key); success = 0; } if (sign_using_dsa_sign(message, message_len, &sig, &sig_len, dsa_key, md) && verify_using_dsa_verify(message, message_len, sig, sig_len, dsa_key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } /* Cleanup */ OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testEVP_SignAPI(){ EVP_PKEY *key = NULL; const unsigned char message[] = "testEVP_SignAPI message"; const EVP_MD *md = EVP_sha224(); const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; /* Test 1: EVP_Sign API */ printf("1. EVP_Sign API: "); if (sign_using_evp_sign(message, message_len, &sig, &sig_len, key, md) && verify_using_evp_verify(message, message_len, sig, sig_len, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testEVP_DigestSignAPI(){ EVP_PKEY *key = NULL; const unsigned char message[] = "testEVP_DigestSignAPI message"; const EVP_MD *md = EVP_sha224(); const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; /* Test 2: EVP_DigestSign API */ printf("2. EVP_DigestSign API: "); if (sign_using_evp_digestsign(message, message_len, &sig, &sig_len, key, md) && verify_using_evp_digestverify(message, message_len, sig, sig_len, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testEVP_PKEY_signAPI(){ EVP_PKEY *key = NULL; const unsigned char message[] = "testEVP_PKEY_signAPI message"; const EVP_MD *md = EVP_sha1(); const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; /* Test 3: EVP_PKEY_sign API (requires pre-hashed input) */ printf("3. EVP_PKEY_sign API: "); if (create_digest(message, message_len, md, digest, &digest_len) && sign_using_evp_pkey_sign(digest, digest_len, &sig, &sig_len, key, md) && verify_using_evp_pkey_verify(digest, digest_len, sig, sig_len, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testEVP_DigestSign_with_ctx(void) { EVP_PKEY *key = NULL; const unsigned char message[] = "testEVP_DigestSign_with_ctx message"; const EVP_MD *md = EVP_sha1(); const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; /* Test 4: EVP_DigestSign with explicit PKEY_CTX */ printf("4. EVP_DigestSign with explicit PKEY_CTX: "); if (sign_using_digestsign_with_ctx(message, message_len, &sig, &sig_len, key, md) && verify_using_digestverify_with_ctx(message, message_len, sig, sig_len, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } OPENSSL_free(sig); EVP_PKEY_free(key); return success; } int testEVP_PKEY_sign_message(void) { EVP_PKEY *key = NULL; const unsigned char message[] = "testEVP_PKEY_sign_message"; const size_t message_len = strlen((char *)message); unsigned char *sig = NULL; size_t sig_len = 0; int success = 1; EVP_PKEY_CTX *key_ctx = NULL; key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); if (!key_ctx) return NULL; if (EVP_PKEY_keygen_init(key_ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, 2048) <= 0 || EVP_PKEY_keygen(key_ctx, &key) <= 0) { EVP_PKEY_free(key); key = NULL; } EVP_PKEY_CTX_free(key_ctx); if (!key) return 0; printf("6. EVP_PKEY_sign_message API: "); if (sign_using_evp_pkey_sign_message(message, message_len, &sig, &sig_len, key, "RSA-SHA256") && verify_using_evp_pkey_verify_message(message, message_len, sig, sig_len, key, "RSA-SHA256")) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } OPENSSL_free(sig); EVP_PKEY_free(key); return success; }