// #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); } /** * Helper to extract key from EVP_PKEY */ static RSA* get_rsa_from_pkey(EVP_PKEY *pkey) { return EVP_PKEY_get1_RSA(pkey); } static DSA* get_dsa_from_pkey(EVP_PKEY *pkey) { return EVP_PKEY_get1_DSA(pkey); } /* ============================================================================= * 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, int (*param_setter)(EVP_PKEY_CTX *ctx)) { 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; } if (param_setter && param_setter(pkey_ctx) != 1) goto cleanup; 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, int (*param_setter)(EVP_PKEY_CTX *ctx)) { 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; } if (param_setter && param_setter(pkey_ctx) != 1) goto cleanup; 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 EVP_MD *md, 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 EVP_MD *md, 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, const EVP_MD *md) { unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; int ret = 0; if (!create_digest(message, message_len, md, digest, &digest_len)) return 0; *signature_len = RSA_size(rsa_key); *signature = OPENSSL_malloc(*signature_len); if (!*signature) return 0; if (RSA_sign(hash_nid, digest, digest_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, const EVP_MD *md) { unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; if (!create_digest(message, message_len, md, digest, &digest_len)) return 0; return RSA_verify(hash_nid, digest, digest_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 * ============================================================================= */ /** * Set RSA PSS padding mode */ int set_rsa_pss_padding(EVP_PKEY_CTX *ctx) { return EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); } /** * No-op parameter setter for default behavior */ int no_parameter_setter(EVP_PKEY_CTX *ctx) { return 1; } /* ============================================================================= * 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 * ============================================================================= */ /** * Test all signature APIs with a given key and algorithm * Demonstrates the 6 different signature API approaches */ int test_signature_apis(EVP_PKEY *key, const EVP_MD *md, int (*param_setter)(EVP_PKEY_CTX *ctx), const char *algo_name) { const unsigned char message[] = "Test message for OpenSSL signature APIs"; const size_t message_len = strlen((char *)message); unsigned char *sig1 = NULL, *sig2 = NULL, *sig3 = NULL, *sig4 = NULL, *sig6 = NULL; size_t sig_len1 = 0, sig_len2 = 0, sig_len3 = 0, sig_len4 = 0, sig_len6 = 0; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len; int success = 1; printf("\nTesting signature APIs with %s:\n", algo_name); /* Test 1: EVP_Sign API */ printf("1. EVP_Sign API: "); if (sign_using_evp_sign(message, message_len, &sig1, &sig_len1, key, md) && verify_using_evp_verify(message, message_len, sig1, sig_len1, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } /* Test 2: EVP_DigestSign API */ printf("2. EVP_DigestSign API: "); if (sign_using_evp_digestsign(message, message_len, &sig2, &sig_len2, key, md) && verify_using_evp_digestverify(message, message_len, sig2, sig_len2, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 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, &sig3, &sig_len3, key, md) && verify_using_evp_pkey_verify(digest, digest_len, sig3, sig_len3, key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 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, &sig4, &sig_len4, key, md, param_setter) && verify_using_digestverify_with_ctx(message, message_len, sig4, sig_len4, key, md, param_setter)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } /* Test 6: EVP_PKEY_sign_message API */ printf("6. EVP_PKEY_sign_message API: "); if (sign_using_evp_pkey_sign_message(message, message_len, &sig6, &sig_len6, key, md, algo_name) && verify_using_evp_pkey_verify_message(message, message_len, sig6, sig_len6, key, md, algo_name)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } /* Cleanup */ OPENSSL_free(sig1); OPENSSL_free(sig2); OPENSSL_free(sig3); OPENSSL_free(sig4); OPENSSL_free(sig6); return success; } /** * Test RSA-specific signature APIs including low-level RSA functions */ int test_signature_apis_rsa(void) { EVP_PKEY *key = NULL; RSA *rsa_key = NULL; const EVP_MD *md = EVP_sha256(); const unsigned char message[] = "Test message for OpenSSL signature APIs"; const size_t message_len = strlen((char *)message); unsigned char *sig5 = NULL; size_t sig_len5 = 0; int success = 1; printf("\nGenerating RSA key pair...\n"); key = generate_rsa_key(); if (!key) return 0; rsa_key = get_rsa_from_pkey(key); if (!rsa_key) { EVP_PKEY_free(key); return 0; } /* Test generic APIs */ if (!test_signature_apis(key, md, set_rsa_pss_padding, "RSA-SHA256")) { success = 0; } /* Test 5: Low-level RSA API */ printf("5. Low-level RSA API: "); if (sign_using_rsa_sign(message, message_len, &sig5, &sig_len5, rsa_key, NID_sha256, md) && verify_using_rsa_verify(message, message_len, sig5, sig_len5, rsa_key, NID_sha256, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } printf("\nRSA API Summary:\n"); printf("1. EVP_Sign API: Legacy, simple\n"); printf("2. EVP_DigestSign API: Modern, recommended\n"); printf("3. EVP_PKEY_sign API: Lower-level, pre-hashed input\n"); printf("4. EVP_DigestSign with PKEY_CTX: Fine-grained control\n"); printf("5. Low-level RSA API: Deprecated, algorithm-specific\n"); printf("6. EVP_PKEY_sign_message API: Streamlined message signing\n"); /* Cleanup */ OPENSSL_free(sig5); RSA_free(rsa_key); EVP_PKEY_free(key); return success; } /** * Test DSA-specific signature APIs including low-level DSA functions */ int test_signature_apis_dsa(void) { EVP_PKEY *key = NULL; DSA *dsa_key = NULL; const EVP_MD *md = EVP_sha256(); const unsigned char message[] = "Test message for OpenSSL signature APIs"; const size_t message_len = strlen((char *)message); unsigned char *sig5 = NULL; size_t sig_len5 = 0; int success = 1; printf("\nGenerating DSA key pair...\n"); key = generate_dsa_key(); if (!key) return 0; dsa_key = get_dsa_from_pkey(key); if (!dsa_key) { EVP_PKEY_free(key); return 0; } /* Test generic APIs */ if (!test_signature_apis(key, md, no_parameter_setter, "dsa")) { success = 0; } /* Test 5: Low-level DSA API */ printf("5. Low-level DSA API: "); if (sign_using_dsa_sign(message, message_len, &sig5, &sig_len5, dsa_key, md) && verify_using_dsa_verify(message, message_len, sig5, sig_len5, dsa_key, md)) { printf("PASS\n"); } else { printf("FAIL\n"); success = 0; } printf("\nDSA API Summary:\n"); printf("1. EVP_Sign API: Legacy, simple\n"); printf("2. EVP_DigestSign API: Modern, recommended\n"); printf("3. EVP_PKEY_sign API: Lower-level, pre-hashed input\n"); printf("4. EVP_DigestSign with PKEY_CTX: Fine-grained control\n"); printf("5. Low-level DSA API: Deprecated, algorithm-specific\n"); printf("6. EVP_PKEY_sign_message API: Streamlined message signing\n"); /* Cleanup */ OPENSSL_free(sig5); EVP_PKEY_free(key); return success; } /* ============================================================================= * MAIN FUNCTION - Entry point for testing all signature APIs * ============================================================================= */ // /** // * Main function demonstrating all OpenSSL signature APIs // * Tests both RSA and DSA algorithms with all 6 API approaches // */ // int main(void) { // /* Initialize OpenSSL */ // OpenSSL_add_all_algorithms(); // ERR_load_crypto_strings(); // printf("=================================================================\n"); // printf("OpenSSL Signature API Demonstration\n"); // printf("=================================================================\n"); // printf("\n-------- TESTING RSA SIGNATURES --------\n"); // int rsa_result = test_signature_apis_rsa(); // printf("\n-------- TESTING DSA SIGNATURES --------\n"); // int dsa_result = test_signature_apis_dsa(); // printf("\n=================================================================\n"); // if (rsa_result && dsa_result) { // printf("All tests completed successfully.\n"); // return 0; // } else { // printf("Some tests failed.\n"); // return 1; // } // }