int aws_cryptosdk_rsa_encrypt()

in source/cipher.c [959:1008]


int aws_cryptosdk_rsa_encrypt(
    struct aws_byte_buf *cipher,
    struct aws_allocator *alloc,
    const struct aws_byte_cursor plain,
    const struct aws_string *rsa_public_key_pem,
    enum aws_cryptosdk_rsa_padding_mode rsa_padding_mode) {
    AWS_PRECONDITION(aws_byte_buf_is_valid(cipher));
    AWS_PRECONDITION(aws_byte_cursor_is_valid(&plain));
    AWS_PRECONDITION(aws_string_is_valid(rsa_public_key_pem));
    if (cipher->buffer) return aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_STATE);
    int padding = get_openssl_rsa_padding_mode(rsa_padding_mode);
    if (padding < 0) return aws_raise_error(AWS_CRYPTOSDK_ERR_UNSUPPORTED_FORMAT);
    BIO *bio          = NULL;
    EVP_PKEY_CTX *ctx = NULL;
    EVP_PKEY *pkey    = NULL;
    bool error        = true;
    int err_code      = AWS_CRYPTOSDK_ERR_CRYPTO_UNKNOWN;
    pkey              = EVP_PKEY_new();
    if (!pkey) goto cleanup;
    bio = BIO_new_mem_buf(aws_string_bytes(rsa_public_key_pem), rsa_public_key_pem->len);
    if (!bio) goto cleanup;
    if (!PEM_read_bio_PUBKEY(bio, &pkey, NULL, NULL)) goto cleanup;
    ctx = EVP_PKEY_CTX_new(pkey, NULL);
    if (!ctx) goto cleanup;
    if (EVP_PKEY_encrypt_init(ctx) <= 0) goto cleanup;
    if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) goto cleanup;
    if (rsa_padding_mode == AWS_CRYPTOSDK_RSA_OAEP_SHA256_MGF1) {
        if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()) <= 0) goto cleanup;
        if (EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()) <= 0) goto cleanup;
    }
    size_t outlen;
    if (EVP_PKEY_encrypt(ctx, NULL, &outlen, plain.ptr, plain.len) <= 0) goto cleanup;
    if (aws_byte_buf_init(cipher, alloc, outlen)) goto cleanup;
    if (1 == EVP_PKEY_encrypt(ctx, cipher->buffer, &outlen, plain.ptr, plain.len)) {
        cipher->len = outlen;
        error       = false;
    }

cleanup:
    EVP_PKEY_CTX_free(ctx);
    EVP_PKEY_free(pkey);
    BIO_free(bio);
    flush_openssl_errors();
    if (error) {
        aws_byte_buf_clean_up_secure(cipher);
        return aws_raise_error(err_code);
    } else {
        return AWS_OP_SUCCESS;
    }
}