1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 /**
5 @file gcm_memory.c
6 GCM implementation, process a packet, by Tom St Denis
7 */
8 #include "tomcrypt_private.h"
9
10 #ifdef LTC_GCM_MODE
11
12 /**
13 Process an entire GCM packet in one call.
14 @param cipher Index of cipher to use
15 @param key The secret key
16 @param keylen The length of the secret key
17 @param IV The initialization vector
18 @param IVlen The length of the initialization vector
19 @param adata The additional authentication data (header)
20 @param adatalen The length of the adata
21 @param pt The plaintext
22 @param ptlen The length of the plaintext (ciphertext length is the same)
23 @param ct The ciphertext
24 @param tag [out] The MAC tag
25 @param taglen [in/out] The MAC tag length
26 @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT)
27 @return CRYPT_OK on success
28 */
gcm_memory(int cipher,const unsigned char * key,unsigned long keylen,const unsigned char * IV,unsigned long IVlen,const unsigned char * adata,unsigned long adatalen,unsigned char * pt,unsigned long ptlen,unsigned char * ct,unsigned char * tag,unsigned long * taglen,int direction)29 int gcm_memory( int cipher,
30 const unsigned char *key, unsigned long keylen,
31 const unsigned char *IV, unsigned long IVlen,
32 const unsigned char *adata, unsigned long adatalen,
33 unsigned char *pt, unsigned long ptlen,
34 unsigned char *ct,
35 unsigned char *tag, unsigned long *taglen,
36 int direction)
37 {
38 void *orig;
39 gcm_state *gcm;
40 int err;
41
42 if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
43 return err;
44 }
45
46 if (cipher_descriptor[cipher]->accel_gcm_memory != NULL) {
47 return cipher_descriptor[cipher]->accel_gcm_memory
48 (key, keylen,
49 IV, IVlen,
50 adata, adatalen,
51 pt, ptlen,
52 ct,
53 tag, taglen,
54 direction);
55 }
56
57
58
59 #ifndef LTC_GCM_TABLES_SSE2
60 orig = gcm = XMALLOC(sizeof(*gcm));
61 #else
62 orig = gcm = XMALLOC(sizeof(*gcm) + 16);
63 #endif
64 if (gcm == NULL) {
65 return CRYPT_MEM;
66 }
67
68 /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations
69 * note that we only modify gcm and keep orig intact. This code is not portable
70 * but again it's only for SSE2 anyways, so who cares?
71 */
72 #ifdef LTC_GCM_TABLES_SSE2
73 gcm = LTC_ALIGN_BUF(gcm, 16);
74 #endif
75
76 if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
77 goto LTC_ERR;
78 }
79 if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) {
80 goto LTC_ERR;
81 }
82 if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) {
83 goto LTC_ERR;
84 }
85 if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) {
86 goto LTC_ERR;
87 }
88 if (direction == GCM_ENCRYPT) {
89 if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) {
90 goto LTC_ERR;
91 }
92 }
93 else if (direction == GCM_DECRYPT) {
94 unsigned char buf[MAXBLOCKSIZE];
95 unsigned long buflen = sizeof(buf);
96 if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) {
97 goto LTC_ERR;
98 }
99 if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) {
100 err = CRYPT_ERROR;
101 }
102 }
103 else {
104 err = CRYPT_INVALID_ARG;
105 }
106 LTC_ERR:
107 gcm_reset(gcm);
108 XFREE(orig);
109 return err;
110 }
111 #endif
112
113