#include "pgsodium.h" PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_keygen); Datum pgsodium_crypto_aead_ietf_keygen(PG_FUNCTION_ARGS) { size_t result_size = VARHDRSZ + crypto_aead_chacha20poly1305_IETF_KEYBYTES; bytea *result = _pgsodium_zalloc_bytea(result_size); crypto_aead_chacha20poly1305_ietf_keygen(PGSODIUM_UCHARDATA(result)); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_noncegen); Datum pgsodium_crypto_aead_ietf_noncegen(PG_FUNCTION_ARGS) { int result_size = VARHDRSZ + crypto_aead_chacha20poly1305_IETF_NPUBBYTES; bytea *result = _pgsodium_zalloc_bytea(result_size); randombytes_buf(VARDATA(result), crypto_aead_chacha20poly1305_IETF_NPUBBYTES); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_encrypt); Datum pgsodium_crypto_aead_ietf_encrypt(PG_FUNCTION_ARGS) { bytea *message = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *nonce = PG_GETARG_BYTEA_P(2); bytea *key = PG_GETARG_BYTEA_P(3); unsigned long long result_size; bytea *result; ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_chacha20poly1305_IETF_NPUBBYTES, "%s: invalid nonce"); ERRORIF(VARSIZE_ANY_EXHDR(key) != crypto_aead_chacha20poly1305_IETF_KEYBYTES, "%s: invalid key"); result_size = VARSIZE_ANY(message) + crypto_aead_chacha20poly1305_IETF_ABYTES; result = _pgsodium_zalloc_bytea(result_size); crypto_aead_chacha20poly1305_ietf_encrypt(PGSODIUM_UCHARDATA(result), &result_size, PGSODIUM_UCHARDATA(message), VARSIZE_ANY_EXHDR(message), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), NULL, PGSODIUM_UCHARDATA(nonce), PGSODIUM_UCHARDATA(key)); SET_VARSIZE(result, result_size + VARHDRSZ + crypto_aead_chacha20poly1305_IETF_ABYTES); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_decrypt); Datum pgsodium_crypto_aead_ietf_decrypt(PG_FUNCTION_ARGS) { bytea *ciphertext = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *nonce = PG_GETARG_BYTEA_P(2); bytea *key = PG_GETARG_BYTEA_P(3); size_t ciphertext_len; unsigned long long result_size; bytea *result; int success; ERRORIF(VARSIZE_ANY_EXHDR(ciphertext) <= crypto_aead_chacha20poly1305_IETF_ABYTES, "%s: invalid message"); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_chacha20poly1305_IETF_NPUBBYTES, "%s: invalid nonce"); ERRORIF(VARSIZE_ANY_EXHDR(key) != crypto_aead_chacha20poly1305_IETF_KEYBYTES, "%s: invalid key"); ciphertext_len = VARSIZE_ANY_EXHDR(ciphertext) - crypto_aead_chacha20poly1305_IETF_ABYTES; result = _pgsodium_zalloc_bytea(ciphertext_len + VARHDRSZ); success = crypto_aead_chacha20poly1305_ietf_decrypt( PGSODIUM_UCHARDATA(result), &result_size, NULL, PGSODIUM_UCHARDATA(ciphertext), ciphertext_len, PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), PGSODIUM_UCHARDATA(nonce), PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: invalid ciphertext"); SET_VARSIZE(result, VARHDRSZ + result_size); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_encrypt_by_id); Datum pgsodium_crypto_aead_ietf_encrypt_by_id(PG_FUNCTION_ARGS) { bytea *message = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *nonce = PG_GETARG_BYTEA_P(2); unsigned long long key_id = PG_GETARG_INT64(3); bytea *context = PG_GETARG_BYTEA_P(4); unsigned long long result_size; bytea *result; bytea *key; ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_chacha20poly1305_IETF_NPUBBYTES, "%s: invalid nonce"); key = pgsodium_derive_helper( key_id, crypto_aead_chacha20poly1305_IETF_KEYBYTES, context); result_size = VARSIZE_ANY(message) + crypto_aead_chacha20poly1305_IETF_ABYTES; result = _pgsodium_zalloc_bytea(result_size); crypto_aead_chacha20poly1305_ietf_encrypt(PGSODIUM_UCHARDATA(result), &result_size, PGSODIUM_UCHARDATA(message), VARSIZE_ANY_EXHDR(message), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), NULL, PGSODIUM_UCHARDATA(nonce), PGSODIUM_UCHARDATA(key)); SET_VARSIZE(result, VARHDRSZ + result_size + crypto_aead_chacha20poly1305_IETF_ABYTES); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_ietf_decrypt_by_id); Datum pgsodium_crypto_aead_ietf_decrypt_by_id(PG_FUNCTION_ARGS) { bytea *ciphertext = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *nonce = PG_GETARG_BYTEA_P(2); unsigned long long key_id = PG_GETARG_INT64(3); bytea *context = PG_GETARG_BYTEA_P(4); size_t ciphertext_len; unsigned long long result_size; bytea *result; bytea *key; int success; ERRORIF(VARSIZE_ANY_EXHDR(ciphertext) <= crypto_aead_chacha20poly1305_IETF_ABYTES, "%s: invalid message"); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_chacha20poly1305_IETF_NPUBBYTES, "%s: invalid nonce"); key = pgsodium_derive_helper( key_id, crypto_aead_chacha20poly1305_IETF_KEYBYTES, context); ciphertext_len = VARSIZE_ANY_EXHDR(ciphertext) - crypto_aead_chacha20poly1305_IETF_ABYTES; result = _pgsodium_zalloc_bytea(ciphertext_len); success = crypto_aead_chacha20poly1305_ietf_decrypt( PGSODIUM_UCHARDATA(result), &result_size, NULL, PGSODIUM_UCHARDATA(ciphertext), ciphertext_len, PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), PGSODIUM_UCHARDATA(nonce), PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: invalid ciphertext"); SET_VARSIZE(result, VARHDRSZ + result_size); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_keygen); Datum pgsodium_crypto_aead_det_keygen(PG_FUNCTION_ARGS) { size_t result_size = VARHDRSZ + crypto_aead_det_xchacha20_KEYBYTES; bytea *result = _pgsodium_zalloc_bytea(result_size); crypto_aead_det_xchacha20_keygen(PGSODIUM_UCHARDATA(result)); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_noncegen); Datum pgsodium_crypto_aead_det_noncegen(PG_FUNCTION_ARGS) { int result_size = VARHDRSZ + crypto_aead_det_xchacha20_NONCEBYTES; bytea *result = _pgsodium_zalloc_bytea(result_size); randombytes_buf(VARDATA(result), crypto_aead_det_xchacha20_NONCEBYTES); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_encrypt); Datum pgsodium_crypto_aead_det_encrypt(PG_FUNCTION_ARGS) { bytea *message = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *key = PG_GETARG_BYTEA_P(2); bytea *nonce; size_t result_size; bytea *result; int success; ERRORIF(VARSIZE_ANY_EXHDR(key) != crypto_aead_det_xchacha20_KEYBYTES, "%s: invalid key"); if (!PG_ARGISNULL(3)) { nonce = PG_GETARG_BYTEA_P(3); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_det_xchacha20_NONCEBYTES, "%s: invalid nonce"); } else { nonce = NULL; } result_size = VARSIZE_ANY_EXHDR(message) + crypto_aead_det_xchacha20_ABYTES; result = _pgsodium_zalloc_bytea(result_size); success = crypto_aead_det_xchacha20_encrypt( PGSODIUM_UCHARDATA(result), PGSODIUM_UCHARDATA(message), VARSIZE_ANY_EXHDR(message), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), nonce != NULL ? PGSODIUM_UCHARDATA(nonce) : NULL, PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: crypto_aead_det_xchacha20_encrypt failed"); SET_VARSIZE(result, VARHDRSZ + result_size); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_decrypt); Datum pgsodium_crypto_aead_det_decrypt(PG_FUNCTION_ARGS) { bytea *ciphertext = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); bytea *key = PG_GETARG_BYTEA_P(2); size_t result_len; bytea *result, *nonce; int success; ERRORIF(VARSIZE_ANY_EXHDR(ciphertext) <= crypto_aead_det_xchacha20_ABYTES, "%s: invalid message"); ERRORIF(VARSIZE_ANY_EXHDR(key) != crypto_aead_det_xchacha20_KEYBYTES, "%s: invalid key"); result_len = VARSIZE_ANY_EXHDR(ciphertext) - crypto_aead_det_xchacha20_ABYTES; result = _pgsodium_zalloc_bytea(result_len); if (!PG_ARGISNULL(3)) { nonce = PG_GETARG_BYTEA_P(3); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_det_xchacha20_NONCEBYTES, "%s: invalid nonce"); } else { nonce = NULL; } success = crypto_aead_det_xchacha20_decrypt( PGSODIUM_UCHARDATA(result), PGSODIUM_UCHARDATA(ciphertext), VARSIZE_ANY_EXHDR(ciphertext), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), nonce != NULL ? PGSODIUM_UCHARDATA(nonce) : NULL, PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: invalid ciphertext"); SET_VARSIZE(result, VARHDRSZ + result_len); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_encrypt_by_id); Datum pgsodium_crypto_aead_det_encrypt_by_id(PG_FUNCTION_ARGS) { bytea *message = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); unsigned long long key_id = PG_GETARG_INT64(2); bytea *context = PG_GETARG_BYTEA_P(3); bytea *key, *nonce; size_t result_size; bytea *result; int success; if (!PG_ARGISNULL(4)) { nonce = PG_GETARG_BYTEA_P(4); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_det_xchacha20_NONCEBYTES, "%s: invalid nonce"); } else { nonce = NULL; } result_size = VARSIZE_ANY_EXHDR(message) + crypto_aead_det_xchacha20_ABYTES; result = _pgsodium_zalloc_bytea(result_size); key = pgsodium_derive_helper( key_id, crypto_aead_det_xchacha20_KEYBYTES, context); success = crypto_aead_det_xchacha20_encrypt( PGSODIUM_UCHARDATA(result), PGSODIUM_UCHARDATA(message), VARSIZE_ANY_EXHDR(message), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), nonce != NULL ? PGSODIUM_UCHARDATA(nonce) : NULL, PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: failed"); SET_VARSIZE(result, VARHDRSZ + result_size); PG_RETURN_BYTEA_P(result); } PG_FUNCTION_INFO_V1(pgsodium_crypto_aead_det_decrypt_by_id); Datum pgsodium_crypto_aead_det_decrypt_by_id(PG_FUNCTION_ARGS) { bytea *ciphertext = PG_GETARG_BYTEA_P(0); bytea *additional = PG_GETARG_BYTEA_P(1); unsigned long long key_id = PG_GETARG_INT64(2); bytea *context = PG_GETARG_BYTEA_P(3); size_t result_len; bytea *key, *result, *nonce; int success; if (!PG_ARGISNULL(4)) { nonce = PG_GETARG_BYTEA_P(4); ERRORIF(VARSIZE_ANY_EXHDR(nonce) != crypto_aead_det_xchacha20_NONCEBYTES, "%s: invalid nonce"); } else { nonce = NULL; } ERRORIF(VARSIZE_ANY_EXHDR(ciphertext) <= crypto_aead_det_xchacha20_ABYTES, "%s: invalid message"); result_len = VARSIZE_ANY_EXHDR(ciphertext) - crypto_aead_det_xchacha20_ABYTES; result = _pgsodium_zalloc_bytea(result_len); key = pgsodium_derive_helper( key_id, crypto_aead_det_xchacha20_KEYBYTES, context); success = crypto_aead_det_xchacha20_decrypt( PGSODIUM_UCHARDATA(result), PGSODIUM_UCHARDATA(ciphertext), VARSIZE_ANY_EXHDR(ciphertext), PGSODIUM_UCHARDATA(additional), VARSIZE_ANY_EXHDR(additional), nonce != NULL ? PGSODIUM_UCHARDATA(nonce) : NULL, PGSODIUM_UCHARDATA(key)); ERRORIF(success != 0, "%s: invalid ciphertext"); SET_VARSIZE(result, VARHDRSZ + result_len); PG_RETURN_BYTEA_P(result); }