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