static void qcrypto_secret_decode(const uint8_t *input, size_t inputlen, uint8_t **output, size_t *outputlen, Error **errp) { *output = qbase64_decode((const gchar*)input, inputlen, outputlen, errp); }
static void test_base64_bad(const char *input, size_t input_len) { size_t len; Error *err = NULL; uint8_t *actual = qbase64_decode(input, input_len, &len, &err); g_assert(err != NULL); g_assert(actual == NULL); g_assert_cmpint(len, ==, 0); error_free(err); }
static void test_base64_good(void) { const char input[] = "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\n" "lzc2VkIHRoZSBzY29ycGlvbi4="; const char expect[] = "Because we focused on the snake, " "we missed the scorpion."; size_t len; uint8_t *actual = qbase64_decode(input, -1, &len, &error_abort); g_assert(actual != NULL); g_assert_cmpint(len, ==, strlen(expect)); g_assert_cmpstr((char *)actual, ==, expect); g_free(actual); }
static void qcrypto_secret_decrypt(QCryptoSecret *secret, const uint8_t *input, size_t inputlen, uint8_t **output, size_t *outputlen, Error **errp) { uint8_t *key = NULL, *ciphertext = NULL, *iv = NULL; size_t keylen, ciphertextlen, ivlen; QCryptoCipher *aes = NULL; uint8_t *plaintext = NULL; *output = NULL; *outputlen = 0; if (qcrypto_secret_lookup(secret->keyid, &key, &keylen, errp) < 0) { goto cleanup; } if (keylen != 32) { error_setg(errp, "Key should be 32 bytes in length"); goto cleanup; } if (!secret->iv) { error_setg(errp, "IV is required to decrypt secret"); goto cleanup; } iv = qbase64_decode(secret->iv, -1, &ivlen, errp); if (!iv) { goto cleanup; } if (ivlen != 16) { error_setg(errp, "IV should be 16 bytes in length not %zu", ivlen); goto cleanup; } aes = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_256, QCRYPTO_CIPHER_MODE_CBC, key, keylen, errp); if (!aes) { goto cleanup; } if (qcrypto_cipher_setiv(aes, iv, ivlen, errp) < 0) { goto cleanup; } if (secret->format == QCRYPTO_SECRET_FORMAT_BASE64) { ciphertext = qbase64_decode((const gchar*)input, inputlen, &ciphertextlen, errp); if (!ciphertext) { goto cleanup; } plaintext = g_new0(uint8_t, ciphertextlen + 1); } else { ciphertextlen = inputlen; plaintext = g_new0(uint8_t, inputlen + 1); } if (qcrypto_cipher_decrypt(aes, ciphertext ? ciphertext : input, plaintext, ciphertextlen, errp) < 0) { plaintext = NULL; goto cleanup; } if (plaintext[ciphertextlen - 1] > 16 || plaintext[ciphertextlen - 1] > ciphertextlen) { error_setg(errp, "Incorrect number of padding bytes (%d) " "found on decrypted data", (int)plaintext[ciphertextlen - 1]); g_free(plaintext); plaintext = NULL; goto cleanup; } /* Even though plaintext may contain arbitrary NUL * ensure it is explicitly NUL terminated. */ ciphertextlen -= plaintext[ciphertextlen - 1]; plaintext[ciphertextlen] = '\0'; *output = plaintext; *outputlen = ciphertextlen; cleanup: g_free(ciphertext); g_free(iv); g_free(key); qcrypto_cipher_free(aes); }