soter_status_t soter_sym_aead_ctx_final(soter_sym_ctx_t *ctx,bool encrypt){ uint8_t out_data[16]; size_t out_data_length=0; if(encrypt){ SOTER_CHECK(EVP_EncryptFinal(&(ctx->evp_sym_ctx), out_data, (int*)&out_data_length)!=0 && out_data_length==0); } else { SOTER_CHECK(EVP_DecryptFinal(&(ctx->evp_sym_ctx), out_data, (int*)&out_data_length)!=0 && out_data_length==0); } return SOTER_SUCCESS; }
soter_status_t soter_sym_aead_encrypt_final(soter_sym_ctx_t *ctx, void* auth_tag, size_t* auth_tag_length){ SOTER_CHECK_PARAM(auth_tag!=NULL); if((*auth_tag_length)<SOTER_AES_GCM_AUTH_TAG_LENGTH){ (*auth_tag_length)=SOTER_AES_GCM_AUTH_TAG_LENGTH; return SOTER_BUFFER_TOO_SMALL; } SOTER_CHECK(soter_sym_aead_ctx_final(ctx, true)==SOTER_SUCCESS); SOTER_CHECK(EVP_CIPHER_CTX_ctrl(&(ctx->evp_sym_ctx), EVP_CTRL_GCM_GET_TAG, SOTER_AES_GCM_AUTH_TAG_LENGTH, auth_tag)); (*auth_tag_length)=SOTER_AES_GCM_AUTH_TAG_LENGTH; return SOTER_SUCCESS; }
soter_status_t soter_sym_ctx_update(soter_sym_ctx_t *ctx, const void* in_data, const size_t in_data_length, void* out_data, size_t* out_data_length, bool encrypt){ if(encrypt){ SOTER_CHECK(EVP_EncryptUpdate(&(ctx->evp_sym_ctx), out_data, (int*)out_data_length, (void*)in_data, in_data_length)==1); } else { SOTER_CHECK(EVP_DecryptUpdate(&(ctx->evp_sym_ctx), out_data, (int*)out_data_length, (void*)in_data, in_data_length)==1); } return SOTER_SUCCESS; }
soter_status_t soter_sym_aead_decrypt_final(soter_sym_ctx_t *ctx, const void* auth_tag, const size_t auth_tag_length) { SOTER_CHECK_PARAM(auth_tag!=NULL); SOTER_CHECK_PARAM(auth_tag_length>=SOTER_AES_GCM_AUTH_TAG_LENGTH); SOTER_CHECK(ctx!=NULL); SOTER_IF_FAIL(EVP_CIPHER_CTX_ctrl(&(ctx->evp_sym_ctx), EVP_CTRL_GCM_SET_TAG, SOTER_AES_GCM_AUTH_TAG_LENGTH, (void*)auth_tag), soter_sym_aead_decrypt_destroy(ctx)); return soter_sym_aead_ctx_final(ctx, false); }
soter_status_t soter_sym_ctx_final(soter_sym_ctx_t *ctx, void* out_data, size_t* out_data_length, bool encrypt){ if((ctx->alg&SOTER_SYM_PADDING_MASK)!=0){ if((*out_data_length)<EVP_CIPHER_CTX_block_size(&(ctx->evp_sym_ctx))){ (*out_data_length)=EVP_CIPHER_CTX_block_size(&(ctx->evp_sym_ctx)); return SOTER_BUFFER_TOO_SMALL; } } if(encrypt){ SOTER_CHECK(EVP_EncryptFinal(&(ctx->evp_sym_ctx), out_data, (int*)out_data_length)!=0); } else { SOTER_CHECK(EVP_DecryptFinal(&(ctx->evp_sym_ctx), out_data, (int*)out_data_length)!=0); } return SOTER_SUCCESS; }
soter_status_t soter_rsa_key_pair_gen_init(soter_rsa_key_pair_gen_t* ctx, const unsigned key_length){ EVP_PKEY *pkey; pkey = EVP_PKEY_new(); SOTER_CHECK(pkey); /* Only RSA supports asymmetric encryption */ SOTER_IF_FAIL(EVP_PKEY_set_type(pkey, EVP_PKEY_RSA), EVP_PKEY_free(pkey)); ctx->pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL); SOTER_IF_FAIL(ctx->pkey_ctx,EVP_PKEY_free(pkey)); BIGNUM *pub_exp; SOTER_IF_FAIL(EVP_PKEY_keygen_init(ctx->pkey_ctx), EVP_PKEY_CTX_free(ctx->pkey_ctx)); /* Although it seems that OpenSSL/LibreSSL use 0x10001 as default public exponent, we will set it explicitly just in case */ pub_exp = BN_new(); SOTER_CHECK(pub_exp); SOTER_IF_FAIL(BN_set_word(pub_exp, RSA_F4), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); SOTER_IF_FAIL(1 <= EVP_PKEY_CTX_ctrl(ctx->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pub_exp), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); /* Override default key size for RSA key. Currently OpenSSL has default key size of 1024. LibreSSL has 2048. We will put 2048 explicitly */ SOTER_IF_FAIL((1 <= EVP_PKEY_CTX_ctrl(ctx->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, rsa_key_length(key_length), NULL)), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); SOTER_IF_FAIL(EVP_PKEY_keygen(ctx->pkey_ctx, &pkey), (BN_free(pub_exp), EVP_PKEY_CTX_free(ctx->pkey_ctx))); return SOTER_SUCCESS; }
soter_status_t soter_rsa_key_pair_gen_destroy(soter_rsa_key_pair_gen_t* ctx){ SOTER_CHECK_PARAM(ctx); SOTER_CHECK(soter_rsa_key_pair_gen_cleanup(ctx)==SOTER_SUCCESS); free(ctx); return SOTER_SUCCESS; }