/** GCM multiply by H @param gcm The GCM state which holds the H value @param I The value to multiply H by */ void gcm_mult_h(gcm_state *gcm, unsigned char *I) { unsigned char T[16]; #ifdef GCM_TABLES int x, y; #ifdef GCM_TABLES_SSE2 asm("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0])); for (x = 1; x < 16; x++) { asm("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0])); } asm("movdqa %%xmm0,(%0)"::"r"(&T)); #else XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&gcm->PC[x][I[x]][y])); } #else for (y = 0; y < 16; y++) { T[y] ^= gcm->PC[x][I[x]][y]; } #endif /* LTC_FAST */ } #endif /* GCM_TABLES_SSE2 */ #else gcm_gf_mult(gcm->H, I, T); #endif XMEMCPY(I, T, 16); }
/** Set the IV for LRW @param IV The IV, must be 16 octets @param len Length ... must be 16 :-) @param lrw The LRW state to update @return CRYPT_OK if successful */ int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw) { int err; #ifdef LTC_LRW_TABLES unsigned char T[16]; int x, y; #endif LTC_ARGCHK(IV != NULL); LTC_ARGCHK(lrw != NULL); if (len != 16) { return CRYPT_INVALID_ARG; } if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { return err; } /* copy the IV */ XMEMCPY(lrw->IV, IV, 16); /* check if we have to actually do work */ if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) { /* we have accelerators, let's bail since they don't use lrw->pad anyways */ return CRYPT_OK; } #ifdef LTC_LRW_TABLES XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16); for (x = 1; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(T + y)) ^= *((LTC_FAST_TYPE *)(&lrw->PC[x][IV[x]][y])); } #else for (y = 0; y < 16; y++) { T[y] ^= lrw->PC[x][IV[x]][y]; } #endif } XMEMCPY(lrw->pad, T, 16); #else gcm_gf_mult(lrw->tweak, IV, lrw->pad); #endif return CRYPT_OK; }
/** Process blocks with LRW, since decrypt/encrypt are largely the same they share this code. @param pt The "input" data @param ct [out] The "output" data @param len The length of the input, must be a multiple of 128-bits (16 octets) @param mode LRW_ENCRYPT or LRW_DECRYPT @param lrw The LRW state @return CRYPT_OK if successful */ int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw) { unsigned char prod[16]; int x, err; #ifdef LTC_LRW_TABLES int y; #endif LTC_ARGCHK(pt != NULL); LTC_ARGCHK(ct != NULL); LTC_ARGCHK(lrw != NULL); if (len & 15) { return CRYPT_INVALID_ARG; } while (len) { /* copy pad */ XMEMCPY(prod, lrw->pad, 16); /* increment IV */ for (x = 15; x >= 0; x--) { lrw->IV[x] = (lrw->IV[x] + 1) & 255; if (lrw->IV[x]) { break; } } /* update pad */ #ifdef LTC_LRW_TABLES /* for each byte changed we undo it's affect on the pad then add the new product */ for (; x < 16; x++) { #ifdef LTC_FAST for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(lrw->pad + y)) ^= *((LTC_FAST_TYPE *)(&lrw->PC[x][lrw->IV[x]][y])) ^ *((LTC_FAST_TYPE *)(&lrw->PC[x][(lrw->IV[x]-1)&255][y])); } #else for (y = 0; y < 16; y++) { lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y]; } #endif } #else gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad); #endif /* xor prod */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(ct + x)) = *((LTC_FAST_TYPE *)(pt + x)) ^ *((LTC_FAST_TYPE *)(prod + x)); } #else for (x = 0; x < 16; x++) { ct[x] = pt[x] ^ prod[x]; } #endif /* send through cipher */ if (mode == LRW_ENCRYPT) { if ((err = cipher_descriptor[lrw->cipher].ecb_encrypt(ct, ct, &lrw->key)) != CRYPT_OK) { return err; } } else { if ((err = cipher_descriptor[lrw->cipher].ecb_decrypt(ct, ct, &lrw->key)) != CRYPT_OK) { return err; } } /* xor prod */ #ifdef LTC_FAST for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { *((LTC_FAST_TYPE *)(ct + x)) = *((LTC_FAST_TYPE *)(ct + x)) ^ *((LTC_FAST_TYPE *)(prod + x)); } #else for (x = 0; x < 16; x++) { ct[x] = ct[x] ^ prod[x]; } #endif /* move to next */ pt += 16; ct += 16; len -= 16; } return CRYPT_OK; }
/** Initialize the LRW context @param cipher The cipher desired, must be a 128-bit block cipher @param IV The index value, must be 128-bits @param key The cipher key @param keylen The length of the cipher key in octets @param tweak The tweak value (second key), must be 128-bits @param num_rounds The number of rounds for the cipher (0 == default) @param lrw [out] The LRW state @return CRYPT_OK on success. */ int lrw_start( int cipher, const unsigned char *IV, const unsigned char *key, int keylen, const unsigned char *tweak, int num_rounds, symmetric_LRW *lrw) { int err; #ifdef LTC_LRW_TABLES unsigned char B[16]; int x, y, z, t; #endif LTC_ARGCHK(IV != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(tweak != NULL); LTC_ARGCHK(lrw != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* is cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher].block_length != 16) { return CRYPT_INVALID_CIPHER; } /* schedule key */ if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &lrw->key)) != CRYPT_OK) { return err; } lrw->cipher = cipher; /* copy the IV and tweak */ XMEMCPY(lrw->tweak, tweak, 16); #ifdef LTC_LRW_TABLES /* setup tables */ /* generate the first table as it has no shifting (from which we make the other tables) */ zeromem(B, 16); for (y = 0; y < 256; y++) { B[0] = y; gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]); } /* now generate the rest of the tables based the previous table */ for (x = 1; x < 16; x++) { for (y = 0; y < 256; y++) { /* now shift it right by 8 bits */ t = lrw->PC[x-1][y][15]; for (z = 15; z > 0; z--) { lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1]; } lrw->PC[x][y][0] = gcm_shift_table[t<<1]; lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; } } #endif /* generate first pad */ return lrw_setiv(IV, 16, lrw); }
/** Initialize a GCM state @param gcm The GCM state to initialize @param cipher The index of the cipher to use @param key The secret key @param keylen The length of the secret key @return CRYPT_OK on success */ int gcm_init(gcm_state *gcm, int cipher, const unsigned char *key, int keylen) { int err; unsigned char B[16]; #ifdef GCM_TABLES int x, y, z, t; #endif LTC_ARGCHK(gcm != NULL); LTC_ARGCHK(key != NULL); #ifdef LTC_FAST if (16 % sizeof(LTC_FAST_TYPE)) { return CRYPT_INVALID_ARG; } #endif /* is cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } if (cipher_descriptor[cipher].block_length != 16) { return CRYPT_INVALID_CIPHER; } /* schedule key */ if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) { return err; } /* H = E(0) */ zeromem(B, 16); if ((err = cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) { return err; } /* setup state */ zeromem(gcm->buf, sizeof(gcm->buf)); zeromem(gcm->X, sizeof(gcm->X)); gcm->cipher = cipher; gcm->mode = GCM_MODE_IV; gcm->ivmode = 0; gcm->buflen = 0; gcm->totlen = 0; gcm->pttotlen = 0; #ifdef GCM_TABLES /* setup tables */ /* generate the first table as it has no shifting (from which we make the other tables) */ zeromem(B, 16); for (y = 0; y < 256; y++) { B[0] = y; gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); } /* now generate the rest of the tables based the previous table */ for (x = 1; x < 16; x++) { for (y = 0; y < 256; y++) { /* now shift it right by 8 bits */ t = gcm->PC[x-1][y][15]; for (z = 15; z > 0; z--) { gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; } gcm->PC[x][y][0] = gcm_shift_table[t<<1]; gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; } } #endif return CRYPT_OK; }