From da5f95035da055dc4480ca17575ac3392efb896a Mon Sep 17 00:00:00 2001 From: wuriyanto Date: Sun, 3 Sep 2023 23:13:30 +0700 Subject: [PATCH] update crypsi --- crypsi.h | 857 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 806 insertions(+), 51 deletions(-) diff --git a/crypsi.h b/crypsi.h index 1992adb..1e718af 100644 --- a/crypsi.h +++ b/crypsi.h @@ -31,6 +31,8 @@ THE SOFTWARE. #include #include +#include +#include #include #define HEX_STRINGS "0123456789abcdef" @@ -81,13 +83,21 @@ enum crypsi_digest_alg { CRYPSI_SHA512, }; +enum crypsi_rsa_modulus { + CRYPSI_RSA_MODULUS_1024 = 1 << 10, + CRYPSI_RSA_MODULUS_2048 = 1 << 11, + CRYPSI_RSA_MODULUS_4096 = 1 << 12 +}; + #ifdef __cplusplus extern "C" { #endif // utilities -int hexencode(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int hexdecode(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); +int hexencode(const unsigned char* message, size_t message_len, + unsigned char** dst, unsigned int* dst_len); +int hexdecode(const unsigned char* message, size_t message_len, + unsigned char** dst, unsigned int* dst_len); unsigned char find_hex_val(unsigned char hx); // AES @@ -134,11 +144,16 @@ int crypsi_aes_256_gcm_decrypt(const unsigned char* key, const unsigned char* da // message digest static int crypsi_digest(enum crypsi_digest_alg alg, const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int crypsi_md5(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int crypsi_sha1(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int crypsi_sha256(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int crypsi_sha384(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); -int crypsi_sha512(const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_md5(const unsigned char* message, + size_t message_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_sha1(const unsigned char* message, + size_t message_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_sha256(const unsigned char* message, + size_t message_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_sha384(const unsigned char* message, + size_t message_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_sha512(const unsigned char* message, + size_t message_len, unsigned char** dst, unsigned int* dst_len); // hmac static int crypsi_hmac(enum crypsi_digest_alg alg, const unsigned char* key, @@ -154,6 +169,66 @@ int crypsi_hmac_sha384(const unsigned char* key, const unsigned char* message, int crypsi_hmac_sha512(const unsigned char* key, const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len); +// RSA +int crypsi_rsa_generate_key_pairs(int size, unsigned char** private_key_buf, + int* private_key_buf_len, unsigned char** public_key_buf, int* public_key_buf_len); +int crypsi_rsa_load_private_key(const unsigned char* buffer, EVP_PKEY** private_key_dst); +int crypsi_rsa_load_public_key(const unsigned char* buffer, EVP_PKEY** public_key_dst); + +// RSA Encryption with OAEP (Optimal Asymmetric Encryption Padding) +static int crypsi_rsa_encrypt_oaep(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_encrypt_oaep_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_encrypt_oaep_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_encrypt_oaep_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_encrypt_oaep_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_encrypt_oaep_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); + +static int crypsi_rsa_decrypt_oaep(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_decrypt_oaep_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_decrypt_oaep_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_decrypt_oaep_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_decrypt_oaep_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_decrypt_oaep_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); + +// RSA DIGITAL SIGNATURE with PSS padding +static int crypsi_rsa_sign_pss(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_sign_pss_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_sign_pss_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_sign_pss_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_sign_pss_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); +int crypsi_rsa_sign_pss_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len); + +static int crypsi_rsa_verify_sign_pss(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char* signature, size_t signature_len); +int crypsi_rsa_verify_sign_pss_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len); +int crypsi_rsa_verify_sign_pss_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len); +int crypsi_rsa_verify_sign_pss_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len); +int crypsi_rsa_verify_sign_pss_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len); +int crypsi_rsa_verify_sign_pss_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len); + #ifdef __cplusplus } #endif @@ -226,12 +301,12 @@ int hexdecode(const unsigned char* message, size_t message_len, // MESSAGE DIGEST static int crypsi_digest(enum crypsi_digest_alg alg, const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len) { - EVP_MD_CTX* mdctx; - EVP_MD* md; + EVP_MD_CTX* mdctx = NULL; + EVP_MD* md = NULL; int ret = -1; unsigned int dst_len_tmp = 0; - unsigned char* dst_tmp; + unsigned char* dst_tmp = NULL; switch (alg) { case CRYPSI_MD5: @@ -281,8 +356,14 @@ static int crypsi_digest(enum crypsi_digest_alg alg, const unsigned char* messag ret = 0; cleanup: - EVP_MD_CTX_free(mdctx); - OPENSSL_free(dst_tmp); + if (mdctx != NULL) { + EVP_MD_CTX_free(mdctx); + } + + if (dst_tmp != NULL) { + OPENSSL_free(dst_tmp); + } + return ret; } @@ -310,13 +391,13 @@ int crypsi_sha512(const unsigned char* message, size_t message_len, unsigned cha static int crypsi_hmac(enum crypsi_digest_alg alg, const unsigned char* key, const unsigned char* message, size_t message_len, unsigned char** dst, unsigned int* dst_len) { - EVP_MD_CTX* mdctx; - EVP_MD* md; - EVP_PKEY* pkey; + EVP_MD_CTX* mdctx = NULL; + EVP_MD* md = NULL; + EVP_PKEY* pkey = NULL; int ret = -1; size_t dst_len_tmp = 0; - unsigned char* dst_tmp; + unsigned char* dst_tmp = NULL; if (strlen((char*) key) < HMAC_KEY_MIN_SIZE) { return ret; @@ -374,9 +455,18 @@ static int crypsi_hmac(enum crypsi_digest_alg alg, const unsigned char* key, ret = 0; cleanup: - EVP_MD_CTX_free(mdctx); - EVP_PKEY_free(pkey); - OPENSSL_free(dst_tmp); + if (mdctx != NULL) { + EVP_MD_CTX_free(mdctx); + } + + if (pkey != NULL) { + EVP_PKEY_free(pkey); + } + + if (dst_tmp != NULL) { + OPENSSL_free(dst_tmp); + } + return ret; } @@ -408,15 +498,15 @@ int crypsi_hmac_sha512(const unsigned char* key, const unsigned char* message, // AES static int crypsi_aes_cbc_encrypt(enum crypsi_aes_key aes_key_size, const unsigned char* key, const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { - EVP_CIPHER_CTX *ctx; - EVP_CIPHER* cipher; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER* cipher = NULL; int ret = -1; int dst_len_tmp = 0; int ciphertext_len = 0; int result_len_raw = 0; - unsigned char* dst_tmp_raw; - unsigned char* dst_tmp; + unsigned char* dst_tmp_raw = NULL; + unsigned char* dst_tmp = NULL; unsigned char iv[AES_BLOCK_SIZE]; // After padding and encrypting data, the size of the ciphertext is plaintext_size + (block_size - plaintext_size % block_size) @@ -498,26 +588,34 @@ static int crypsi_aes_cbc_encrypt(enum crypsi_aes_key aes_key_size, const unsign /* Clean up */ cleanup: - EVP_CIPHER_CTX_free(ctx); - free((void*) dst_tmp); - free((void*) dst_tmp_raw); + if (ctx != NULL) { + EVP_CIPHER_CTX_free(ctx); + } + + if (dst_tmp != NULL) { + free((void*) dst_tmp); + } + + if (dst_tmp_raw != NULL) { + free((void*) dst_tmp_raw); + } return ret; } static int crypsi_aes_cbc_decrypt(enum crypsi_aes_key aes_key_size, const unsigned char* key, const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { - EVP_CIPHER_CTX *ctx; - EVP_CIPHER* cipher; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER* cipher = NULL; int ret = -1; int dst_len_tmp = 0; int plaintext_len = 0; int raw_ciphertext_len = 0; - unsigned char* ciphertext_raw; - unsigned char* dst_tmp; + unsigned char* ciphertext_raw = NULL; + unsigned char* dst_tmp = NULL; unsigned char iv[AES_BLOCK_SIZE]; - unsigned char* dst_decode; + unsigned char* dst_decode = NULL; unsigned int dst_decode_len = 0; switch (aes_key_size) { @@ -599,24 +697,36 @@ static int crypsi_aes_cbc_decrypt(enum crypsi_aes_key aes_key_size, const unsign /* Clean up */ cleanup: - EVP_CIPHER_CTX_free(ctx); - free((void*) dst_decode); - free((void*) ciphertext_raw); - free((void*) dst_tmp); + if (ctx != NULL) { + EVP_CIPHER_CTX_free(ctx); + } + + if (dst_decode != NULL) { + free((void*) dst_decode); + } + + if (ciphertext_raw != NULL) { + free((void*) ciphertext_raw); + } + + if (dst_tmp != NULL) { + free((void*) dst_tmp); + } + return ret; } static int crypsi_aes_gcm_encrypt(enum crypsi_aes_key aes_key_size, const unsigned char* key, const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { - EVP_CIPHER_CTX *ctx; - EVP_CIPHER* cipher; + EVP_CIPHER_CTX* ctx = NULL; + EVP_CIPHER* cipher = NULL; int ret = -1; int dst_len_tmp = 0; int ciphertext_len = 0; int result_len_raw = 0; - unsigned char* dst_tmp_raw; - unsigned char* dst_tmp; + unsigned char* dst_tmp_raw = NULL; + unsigned char* dst_tmp = NULL; unsigned char iv[AES_GCM_IV_SIZE]; unsigned char tag[AES_GCM_TAG_SIZE]; @@ -710,27 +820,35 @@ static int crypsi_aes_gcm_encrypt(enum crypsi_aes_key aes_key_size, const unsign /* Clean up */ cleanup: - EVP_CIPHER_CTX_free(ctx); - free((void*) dst_tmp); - free((void*) dst_tmp_raw); + if (ctx != NULL) { + EVP_CIPHER_CTX_free(ctx); + } + + if (dst_tmp != NULL) { + free((void*) dst_tmp); + } + + if (dst_tmp_raw != NULL) { + free((void*) dst_tmp_raw); + } return ret; } static int crypsi_aes_gcm_decrypt(enum crypsi_aes_key aes_key_size, const unsigned char* key, const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { - EVP_CIPHER_CTX *ctx; - EVP_CIPHER* cipher; + EVP_CIPHER_CTX* ctx = NULL; + EVP_CIPHER* cipher = NULL; int ret = -1; int dst_len_tmp = 0; int plaintext_len = 0; int raw_ciphertext_len = 0; - unsigned char* ciphertext_raw; - unsigned char* dst_tmp; + unsigned char* ciphertext_raw = NULL; + unsigned char* dst_tmp = NULL; unsigned char iv[AES_GCM_IV_SIZE]; unsigned char tag[AES_GCM_TAG_SIZE]; - unsigned char* dst_decode; + unsigned char* dst_decode = NULL; unsigned int dst_decode_len = 0; switch (aes_key_size) { @@ -821,10 +939,21 @@ static int crypsi_aes_gcm_decrypt(enum crypsi_aes_key aes_key_size, const unsign /* Clean up */ cleanup: - EVP_CIPHER_CTX_free(ctx); - free((void*) dst_decode); - free((void*) ciphertext_raw); - free((void*) dst_tmp); + if (ctx != NULL) { + EVP_CIPHER_CTX_free(ctx); + } + + if (dst_decode != NULL) { + free((void*) dst_decode); + } + + if (ciphertext_raw != NULL) { + free((void*) ciphertext_raw); + } + + if (dst_tmp != NULL) { + free((void*) dst_tmp); + } return ret; } @@ -891,4 +1020,630 @@ int crypsi_aes_256_gcm_decrypt(const unsigned char* key, const unsigned char* da return crypsi_aes_gcm_decrypt(CRYPSI_AES_256_KEY, key, data, data_len, dst, dst_len); } +// RSA +int crypsi_rsa_generate_key_pairs(int size, unsigned char** private_key_buf, + int* private_key_buf_len, unsigned char** public_key_buf, int* public_key_buf_len) { + int ret = -1; + EVP_PKEY* pkey = NULL; + BIO* private_bio = NULL; + BIO* public_bio = NULL; + int private_key_len; + int public_key_len; + + switch (size) { + case CRYPSI_RSA_MODULUS_1024: + case CRYPSI_RSA_MODULUS_2048: + case CRYPSI_RSA_MODULUS_4096: + break; + default: + return ret; + } + + EVP_PKEY_CTX* key_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (key_ctx == NULL) { + goto cleanup; + } + + if (EVP_PKEY_keygen_init(key_ctx) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_keygen_bits(key_ctx, size) != 1) { + goto cleanup; + } + + if (EVP_PKEY_keygen(key_ctx, &pkey) != 1) { + goto cleanup; + } + + // extract private key as string + // create a place to dump the IO, in this case in memory + private_bio = BIO_new(BIO_s_mem()); + PEM_write_bio_PrivateKey(private_bio, pkey, NULL, NULL, 0, 0, NULL); + + // get buffer length + private_key_len = BIO_pending(private_bio); + *private_key_buf = (unsigned char*) malloc(private_key_len); + BIO_read(private_bio, *private_key_buf, private_key_len); + + *private_key_buf_len = private_key_len; + + // extract public key as string + // create a place to dump the IO, in this case in memory + public_bio = BIO_new(BIO_s_mem()); + PEM_write_bio_PUBKEY(public_bio, pkey); + + // get buffer length + public_key_len = BIO_pending(public_bio); + *public_key_buf = (unsigned char*) malloc(public_key_len); + BIO_read(public_bio, *public_key_buf, public_key_len); + + *public_key_buf_len = public_key_len; + + ret = 0; + + cleanup: + if (key_ctx != NULL) { + EVP_PKEY_CTX_free(key_ctx); + } + + if (pkey != NULL) { + EVP_PKEY_free(pkey); + } + + if (private_bio != NULL) { + BIO_free(private_bio); + } + + if (public_bio != NULL) { + BIO_free(public_bio); + } + + return ret; +} + +int crypsi_rsa_load_private_key(const unsigned char* buffer, EVP_PKEY** private_key_dst) { + int ret = -1; + RSA* rsa_private_key = NULL; + + // key sanitizer + char buffer_tmp[strlen((const char*) buffer)+1]; + int i, j; + for(i = 0, j = 0 ; buffer[i] != '\0'; i++) { + if(buffer[i] == '\\' && buffer[i + 1] == 'n') { + buffer_tmp[j] = '\n'; + i++; + } else { + buffer_tmp[j] = buffer[i]; + } + j++; + } + + buffer_tmp[j] = 0x0; + + // write char array to BIO + BIO* rsa_private_bio = BIO_new_mem_buf(buffer_tmp, -1); + if (rsa_private_bio == NULL) { + goto cleanup; + } + + // create a RSA object from private key char array + if(!PEM_read_bio_RSAPrivateKey(rsa_private_bio, &rsa_private_key, NULL, NULL)) { + goto cleanup; + } + + // create private key + *private_key_dst = EVP_PKEY_new(); + if (*private_key_dst == NULL) { + goto cleanup; + } + + if (EVP_PKEY_assign_RSA(*private_key_dst, rsa_private_key) != 1) { + goto cleanup; + } + + ret = 0; + + // cleanup + cleanup: + if (rsa_private_bio != NULL) { + BIO_free(rsa_private_bio); + } + + return ret; +} + +int crypsi_rsa_load_public_key(const unsigned char* buffer, EVP_PKEY** public_key_dst) { + int ret = -1; + RSA* rsa_public_key = NULL; + + // key sanitizer + char buffer_tmp[strlen((const char*) buffer)+1]; + int i, j; + for(i = 0, j = 0 ; buffer[i] != '\0'; i++) { + if (buffer[i] == '\\' && buffer[i + 1] == 'n') { + buffer_tmp[j] = '\n'; + i++; + } else { + buffer_tmp[j] = buffer[i]; + } + j++; + } + + buffer_tmp[j] = 0x0; + + // write char array to BIO + BIO* rsa_public_bio = BIO_new_mem_buf(buffer_tmp, -1); + if (rsa_public_bio == NULL) { + goto cleanup; + } + + // create a RSA object from public key char array + if(!PEM_read_bio_RSA_PUBKEY(rsa_public_bio, &rsa_public_key, NULL, NULL)) { + goto cleanup; + } + + // create public key + *public_key_dst = EVP_PKEY_new(); + if (*public_key_dst == NULL) { + goto cleanup; + } + + if (EVP_PKEY_assign_RSA(*public_key_dst, rsa_public_key) != 1) { + goto cleanup; + } + + ret = 0; + + // cleanup + cleanup: + if (rsa_public_bio != NULL) { + BIO_free(rsa_public_bio); + } + + return ret; +} + +// RSA Encryption +static int crypsi_rsa_encrypt_oaep(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { + + int ret = -1; + EVP_MD* md = NULL; + EVP_PKEY* public_key = NULL; + EVP_PKEY_CTX* enc_ctx = NULL; + size_t dst_encrypt_len; + unsigned char* dst_encrypt = NULL; + + switch (alg) { + case CRYPSI_MD5: + md = (EVP_MD*) EVP_md5(); + break; + case CRYPSI_SHA1: + md = (EVP_MD*) EVP_sha1(); + break; + case CRYPSI_SHA256: + md = (EVP_MD*) EVP_sha256(); + break; + case CRYPSI_SHA384: + md = (EVP_MD*) EVP_sha384(); + break; + case CRYPSI_SHA512: + md = (EVP_MD*) EVP_sha512(); + break; + default: + return ret; + } + + if (crypsi_rsa_load_public_key(key, &public_key) != 0) { + goto cleanup; + } + + enc_ctx = EVP_PKEY_CTX_new(public_key, NULL); + if (EVP_PKEY_encrypt_init(enc_ctx) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_padding(enc_ctx, RSA_PKCS1_OAEP_PADDING) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_oaep_md(enc_ctx, md) != 1) { + goto cleanup; + } + + // Determine the size of the output + if (EVP_PKEY_encrypt(enc_ctx, NULL, &dst_encrypt_len, data, data_len) != 1) { + goto cleanup; + } + + dst_encrypt = (unsigned char*) malloc((dst_encrypt_len+1)*sizeof(char)); + if (dst_encrypt == NULL) { + goto cleanup; + } + + if (EVP_PKEY_encrypt(enc_ctx, dst_encrypt, &dst_encrypt_len, data, data_len) != 1) { + goto cleanup; + } + + dst_encrypt[dst_encrypt_len] = 0x0; + + if(hexencode(dst_encrypt, dst_encrypt_len, dst, dst_len) != 0) { + goto cleanup; + } + + ret = 0; + + cleanup: + if (enc_ctx != NULL) { + EVP_PKEY_CTX_free(enc_ctx); + } + + if (public_key != NULL) { + EVP_PKEY_free(public_key); + } + + if (dst_encrypt != NULL) { + free((void*) dst_encrypt); + } + + return ret; +} + +static int crypsi_rsa_decrypt_oaep(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { + + int ret = -1; + EVP_MD* md = NULL; + EVP_PKEY* private_key = NULL; + EVP_PKEY_CTX* dec_ctx = NULL; + size_t dst_decrypt_len; + unsigned int dst_decode_len; + unsigned char* dst_decode = NULL; + + switch (alg) { + case CRYPSI_MD5: + md = (EVP_MD*) EVP_md5(); + break; + case CRYPSI_SHA1: + md = (EVP_MD*) EVP_sha1(); + break; + case CRYPSI_SHA256: + md = (EVP_MD*) EVP_sha256(); + break; + case CRYPSI_SHA384: + md = (EVP_MD*) EVP_sha384(); + break; + case CRYPSI_SHA512: + md = (EVP_MD*) EVP_sha512(); + break; + default: + return ret; + } + + if(hexdecode(data, data_len, &dst_decode, &dst_decode_len) != 0) { + goto cleanup; + } + + if (crypsi_rsa_load_private_key(key, &private_key) != 0) { + goto cleanup; + } + + dec_ctx = EVP_PKEY_CTX_new(private_key, NULL); + if (EVP_PKEY_decrypt_init(dec_ctx) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_padding(dec_ctx, RSA_PKCS1_OAEP_PADDING) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_oaep_md(dec_ctx, md) != 1) { + goto cleanup; + } + + // Determine the size of the output + if (EVP_PKEY_decrypt(dec_ctx, NULL, &dst_decrypt_len, dst_decode, dst_decode_len) != 1) { + goto cleanup; + } + + *dst = (unsigned char*) malloc((dst_decrypt_len+1)*sizeof(char)); + if (*dst == NULL) { + goto cleanup; + } + + if (EVP_PKEY_decrypt(dec_ctx, *dst, &dst_decrypt_len, dst_decode, dst_decode_len) != 1) { + goto cleanup; + } + + (*dst)[dst_decrypt_len] = 0x0; + *dst_len = dst_decrypt_len; + + ret = 0; + + cleanup: + if (dec_ctx != NULL) { + EVP_PKEY_CTX_free(dec_ctx); + } + + if (private_key != NULL) { + EVP_PKEY_free(private_key); + } + + if (dst_decode != NULL) { + free((void*) dst_decode); + } + + return ret; +} + +// RSA ENCRYPT +int crypsi_rsa_encrypt_oaep_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_encrypt_oaep(CRYPSI_MD5, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_encrypt_oaep_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_encrypt_oaep(CRYPSI_SHA1, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_encrypt_oaep_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_encrypt_oaep(CRYPSI_SHA256, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_encrypt_oaep_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_encrypt_oaep(CRYPSI_SHA384, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_encrypt_oaep_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_encrypt_oaep(CRYPSI_SHA512, key, data, data_len, dst, dst_len); +} + +// RSA DECRYPT +int crypsi_rsa_decrypt_oaep_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_decrypt_oaep(CRYPSI_MD5, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_decrypt_oaep_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_decrypt_oaep(CRYPSI_SHA1, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_decrypt_oaep_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_decrypt_oaep(CRYPSI_SHA256, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_decrypt_oaep_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_decrypt_oaep(CRYPSI_SHA384, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_decrypt_oaep_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_decrypt_oaep(CRYPSI_SHA512, key, data, data_len, dst, dst_len); +} + +// RSA DIGITAL SIGNATURE +static int crypsi_rsa_sign_pss(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char** dst, unsigned int* dst_len) { + + int ret = -1; + EVP_PKEY* private_key = NULL; + EVP_MD* md = NULL; + EVP_PKEY_CTX* sign_pkey_ctx = NULL; + EVP_MD_CTX* sign_ctx = EVP_MD_CTX_new(); + size_t dst_signature_len; + unsigned char* dst_signature = NULL; + + switch (alg) { + case CRYPSI_MD5: + md = (EVP_MD*) EVP_md5(); + break; + case CRYPSI_SHA1: + md = (EVP_MD*) EVP_sha1(); + break; + case CRYPSI_SHA256: + md = (EVP_MD*) EVP_sha256(); + break; + case CRYPSI_SHA384: + md = (EVP_MD*) EVP_sha384(); + break; + case CRYPSI_SHA512: + md = (EVP_MD*) EVP_sha512(); + break; + default: + return ret; + } + + if (crypsi_rsa_load_private_key(key, &private_key) != 0) { + goto cleanup; + } + + if (EVP_DigestSignInit(sign_ctx, &sign_pkey_ctx, md, NULL, private_key) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_padding(sign_pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(sign_pkey_ctx, RSA_PSS_SALTLEN_DIGEST) != 1) { + goto cleanup; + } + + if (EVP_DigestSignUpdate(sign_ctx, data, data_len) != 1) { + goto cleanup; + } + + // Determine the size of the output + if (EVP_DigestSignFinal(sign_ctx, NULL, &dst_signature_len) != 1) { + goto cleanup; + } + + dst_signature = (unsigned char*) malloc((dst_signature_len+1)*sizeof(char)); + if (dst_signature == NULL) { + goto cleanup; + } + + if (EVP_DigestSignFinal(sign_ctx, dst_signature, &dst_signature_len) != 1) { + goto cleanup; + } + + dst_signature[dst_signature_len] = 0x0; + + if(hexencode(dst_signature, dst_signature_len, dst, dst_len) != 0) { + goto cleanup; + } + + ret = 0; + cleanup: + if (sign_ctx != NULL) { + EVP_MD_CTX_free(sign_ctx); + } + + if (private_key != NULL) { + EVP_PKEY_free(private_key); + } + + if (dst_signature != NULL) { + free((void*) dst_signature); + } + + return ret; +} + +static int crypsi_rsa_verify_sign_pss(enum crypsi_digest_alg alg, const unsigned char* key, + const unsigned char* data, size_t data_len, unsigned char* signature, size_t signature_len) { + + // this function will return + // error = -1 + // succeed with invalid signature = 0 + // succeed with valid signature = 1 + int ret = -1; + EVP_MD* md = NULL; + EVP_PKEY* public_key = NULL; + EVP_PKEY_CTX* verify_pkey_ctx = NULL; + EVP_MD_CTX* verify_ctx = EVP_MD_CTX_new(); + unsigned int dst_decode_len; + unsigned char* dst_decode = NULL; + + switch (alg) { + case CRYPSI_MD5: + md = (EVP_MD*) EVP_md5(); + break; + case CRYPSI_SHA1: + md = (EVP_MD*) EVP_sha1(); + break; + case CRYPSI_SHA256: + md = (EVP_MD*) EVP_sha256(); + break; + case CRYPSI_SHA384: + md = (EVP_MD*) EVP_sha384(); + break; + case CRYPSI_SHA512: + md = (EVP_MD*) EVP_sha512(); + break; + default: + return ret; + } + + if (crypsi_rsa_load_public_key(key, &public_key) != 0) { + goto cleanup; + } + + if(hexdecode(signature, signature_len, &dst_decode, &dst_decode_len) != 0) { + goto cleanup; + } + + if (EVP_DigestVerifyInit(verify_ctx, &verify_pkey_ctx, md, NULL, public_key) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_padding(verify_pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) { + goto cleanup; + } + + if (EVP_PKEY_CTX_set_rsa_pss_saltlen(verify_pkey_ctx, RSA_PSS_SALTLEN_DIGEST) != 1) { + goto cleanup; + } + + if (EVP_DigestVerifyUpdate(verify_ctx, data, data_len) != 1) { + goto cleanup; + } + + ret = EVP_DigestVerifyFinal(verify_ctx, dst_decode, dst_decode_len); + + cleanup: + if (verify_ctx != NULL) { + EVP_MD_CTX_free(verify_ctx); + } + + if (public_key != NULL) { + EVP_PKEY_free(public_key); + } + + if (dst_decode != NULL) { + free((void*) dst_decode); + } + + return ret; +} + +// RSA DIGITAL SIGNATURE (SIGN OPERATION) +int crypsi_rsa_sign_pss_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_sign_pss(CRYPSI_MD5, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_sign_pss_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_sign_pss(CRYPSI_SHA1, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_sign_pss_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_sign_pss(CRYPSI_SHA256, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_sign_pss_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_sign_pss(CRYPSI_SHA384, key, data, data_len, dst, dst_len); +} + +int crypsi_rsa_sign_pss_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char** dst, unsigned int* dst_len) { + return crypsi_rsa_sign_pss(CRYPSI_SHA512, key, data, data_len, dst, dst_len); +} + +// RSA DIGITAL SIGNATURE (VERIFY SIGNATURE OPERATION) +int crypsi_rsa_verify_sign_pss_md5(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len) { + return crypsi_rsa_verify_sign_pss(CRYPSI_MD5, key, data, data_len, signature, signature_len); +} + +int crypsi_rsa_verify_sign_pss_sha1(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len) { + return crypsi_rsa_verify_sign_pss(CRYPSI_SHA1, key, data, data_len, signature, signature_len); +} + +int crypsi_rsa_verify_sign_pss_sha256(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len) { + return crypsi_rsa_verify_sign_pss(CRYPSI_SHA256, key, data, data_len, signature, signature_len); +} + +int crypsi_rsa_verify_sign_pss_sha384(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len) { + return crypsi_rsa_verify_sign_pss(CRYPSI_SHA384, key, data, data_len, signature, signature_len); +} + +int crypsi_rsa_verify_sign_pss_sha512(const unsigned char* key, const unsigned char* data, + size_t data_len, unsigned char* signature, size_t signature_len) { + return crypsi_rsa_verify_sign_pss(CRYPSI_SHA512, key, data, data_len, signature, signature_len); +} #endif \ No newline at end of file