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 if ((unsigned long)gcm & 15) {
74 gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15)));
75 }
76 #endif
77
78 if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
79 goto LTC_ERR;
80 }
81 if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) {
82 goto LTC_ERR;
83 }
84 if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) {
85 goto LTC_ERR;
86 }
87 if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) {
88 goto LTC_ERR;
89 }
90 if (direction == GCM_ENCRYPT) {
91 if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) {
92 goto LTC_ERR;
93 }
94 }
95 else if (direction == GCM_DECRYPT) {
96 unsigned char buf[MAXBLOCKSIZE];
97 unsigned long buflen = sizeof(buf);
98 if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) {
99 goto LTC_ERR;
100 }
101 if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) {
102 err = CRYPT_ERROR;
103 }
104 }
105 else {
106 err = CRYPT_INVALID_ARG;
107 }
108 LTC_ERR:
109 XFREE(orig);
110 return err;
111 }
112 #endif
113
114