Path: blob/main/crypto/openssl/demos/cipher/aesgcm.c
34879 views
/*1* Copyright 2012-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* Simple AES GCM authenticated encryption with additional data (AEAD)11* demonstration program.12*/1314#include <stdio.h>15#include <openssl/err.h>16#include <openssl/bio.h>17#include <openssl/evp.h>18#include <openssl/core_names.h>1920/* AES-GCM test data obtained from NIST public test vectors */2122/* AES key */23static const unsigned char gcm_key[] = {240xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,250x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,260xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f27};2829/* Unique initialisation vector */30static const unsigned char gcm_iv[] = {310x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x8432};3334/* Example plaintext to encrypt */35static const unsigned char gcm_pt[] = {360xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e, 0xeb, 0x31, 0xb2, 0xea,370xcc, 0x2b, 0xf2, 0xa538};3940/*41* Example of Additional Authenticated Data (AAD), i.e. unencrypted data42* which can be authenticated using the generated Tag value.43*/44static const unsigned char gcm_aad[] = {450x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43,460x7f, 0xec, 0x78, 0xde47};4849/* Expected ciphertext value */50static const unsigned char gcm_ct[] = {510xf7, 0x26, 0x44, 0x13, 0xa8, 0x4c, 0x0e, 0x7c, 0xd5, 0x36, 0x86, 0x7e,520xb9, 0xf2, 0x17, 0x3653};5455/* Expected AEAD Tag value */56static const unsigned char gcm_tag[] = {570x67, 0xba, 0x05, 0x10, 0x26, 0x2a, 0xe4, 0x87, 0xd7, 0x37, 0xee, 0x62,580x98, 0xf7, 0x7e, 0x0c59};6061/*62* A library context and property query can be used to select & filter63* algorithm implementations. If they are NULL then the default library64* context and properties are used.65*/66static OSSL_LIB_CTX *libctx = NULL;67static const char *propq = NULL;6869static int aes_gcm_encrypt(void)70{71int ret = 0;72EVP_CIPHER_CTX *ctx;73EVP_CIPHER *cipher = NULL;74int outlen, tmplen;75size_t gcm_ivlen = sizeof(gcm_iv);76unsigned char outbuf[1024];77unsigned char outtag[16];78OSSL_PARAM params[2] = {79OSSL_PARAM_END, OSSL_PARAM_END80};8182printf("AES GCM Encrypt:\n");83printf("Plaintext:\n");84BIO_dump_fp(stdout, gcm_pt, sizeof(gcm_pt));8586/* Create a context for the encrypt operation */87if ((ctx = EVP_CIPHER_CTX_new()) == NULL)88goto err;8990/* Fetch the cipher implementation */91if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq)) == NULL)92goto err;9394/* Set IV length if default 96 bits is not appropriate */95params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,96&gcm_ivlen);9798/*99* Initialise an encrypt operation with the cipher/mode, key, IV and100* IV length parameter.101* For demonstration purposes the IV is being set here. In a compliant102* application the IV would be generated internally so the iv passed in103* would be NULL.104*/105if (!EVP_EncryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))106goto err;107108/* Zero or more calls to specify any AAD */109if (!EVP_EncryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)))110goto err;111112/* Encrypt plaintext */113if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, gcm_pt, sizeof(gcm_pt)))114goto err;115116/* Output encrypted block */117printf("Ciphertext:\n");118BIO_dump_fp(stdout, outbuf, outlen);119120/* Finalise: note get no output for GCM */121if (!EVP_EncryptFinal_ex(ctx, outbuf, &tmplen))122goto err;123124/* Get tag */125params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,126outtag, 16);127128if (!EVP_CIPHER_CTX_get_params(ctx, params))129goto err;130131/* Output tag */132printf("Tag:\n");133BIO_dump_fp(stdout, outtag, 16);134135ret = 1;136err:137if (!ret)138ERR_print_errors_fp(stderr);139140EVP_CIPHER_free(cipher);141EVP_CIPHER_CTX_free(ctx);142143return ret;144}145146static int aes_gcm_decrypt(void)147{148int ret = 0;149EVP_CIPHER_CTX *ctx;150EVP_CIPHER *cipher = NULL;151int outlen, rv;152size_t gcm_ivlen = sizeof(gcm_iv);153unsigned char outbuf[1024];154OSSL_PARAM params[2] = {155OSSL_PARAM_END, OSSL_PARAM_END156};157158printf("AES GCM Decrypt:\n");159printf("Ciphertext:\n");160BIO_dump_fp(stdout, gcm_ct, sizeof(gcm_ct));161162if ((ctx = EVP_CIPHER_CTX_new()) == NULL)163goto err;164165/* Fetch the cipher implementation */166if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq)) == NULL)167goto err;168169/* Set IV length if default 96 bits is not appropriate */170params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,171&gcm_ivlen);172173/*174* Initialise an encrypt operation with the cipher/mode, key, IV and175* IV length parameter.176*/177if (!EVP_DecryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))178goto err;179180/* Zero or more calls to specify any AAD */181if (!EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)))182goto err;183184/* Decrypt plaintext */185if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, gcm_ct, sizeof(gcm_ct)))186goto err;187188/* Output decrypted block */189printf("Plaintext:\n");190BIO_dump_fp(stdout, outbuf, outlen);191192/* Set expected tag value. */193params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,194(void*)gcm_tag, sizeof(gcm_tag));195196if (!EVP_CIPHER_CTX_set_params(ctx, params))197goto err;198199/* Finalise: note get no output for GCM */200rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);201/*202* Print out return value. If this is not successful authentication203* failed and plaintext is not trustworthy.204*/205printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");206207ret = 1;208err:209if (!ret)210ERR_print_errors_fp(stderr);211212EVP_CIPHER_free(cipher);213EVP_CIPHER_CTX_free(ctx);214215return ret;216}217218int main(int argc, char **argv)219{220if (!aes_gcm_encrypt())221return EXIT_FAILURE;222223if (!aes_gcm_decrypt())224return EXIT_FAILURE;225226return EXIT_SUCCESS;227}228229230