xref: /optee_os/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c (revision 2a65ecaf7d6f855e24ce1a117fe1931f7378f82c)
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