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