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 (at) gmail.com, http://libtomcrypt.com 10 */ 11 12 /** 13 @file s_ocb_done.c 14 OCB implementation, internal helper, by Tom St Denis 15 */ 16 #include "tomcrypt.h" 17 18 #ifdef OCB_MODE 19 20 /* Since the last block is encrypted in CTR mode the same code can 21 * be used to finish a decrypt or encrypt stream. The only difference 22 * is we XOR the final ciphertext into the checksum so we have to xor it 23 * before we CTR [decrypt] or after [encrypt] 24 * 25 * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... 26 */ 27 28 /** 29 Shared code to finish an OCB stream 30 @param ocb The OCB state 31 @param pt The remaining plaintext [or input] 32 @param ptlen The length of the input (octets) 33 @param ct [out] The output buffer 34 @param tag [out] The destination for the authentication tag 35 @param taglen [in/out] The max size and resulting size of the authentication tag 36 @param mode The mode we are terminating, 0==encrypt, 1==decrypt 37 @return CRYPT_OK if successful 38 */ 39 int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, 40 unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) 41 42 { 43 unsigned char *Z, *Y, *X; 44 int err, x; 45 46 LTC_ARGCHK(ocb != NULL); 47 LTC_ARGCHK(pt != NULL); 48 LTC_ARGCHK(ct != NULL); 49 LTC_ARGCHK(tag != NULL); 50 LTC_ARGCHK(taglen != NULL); 51 if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { 52 return err; 53 } 54 if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length || 55 (int)ptlen > ocb->block_len || (int)ptlen < 0) { 56 return CRYPT_INVALID_ARG; 57 } 58 59 /* allocate ram */ 60 Z = XMALLOC(MAXBLOCKSIZE); 61 Y = XMALLOC(MAXBLOCKSIZE); 62 X = XMALLOC(MAXBLOCKSIZE); 63 if (X == NULL || Y == NULL || Z == NULL) { 64 if (X != NULL) { 65 XFREE(X); 66 } 67 if (Y != NULL) { 68 XFREE(Y); 69 } 70 if (Z != NULL) { 71 XFREE(Z); 72 } 73 return CRYPT_MEM; 74 } 75 76 /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ 77 ocb_shift_xor(ocb, X); 78 XMEMCPY(Z, X, ocb->block_len); 79 80 X[ocb->block_len-1] ^= (ptlen*8)&255; 81 X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; 82 for (x = 0; x < ocb->block_len; x++) { 83 X[x] ^= ocb->Lr[x]; 84 } 85 86 /* Y[m] = E(X[m])) */ 87 if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key)) != CRYPT_OK) { 88 goto error; 89 } 90 91 if (mode == 1) { 92 /* decrypt mode, so let's xor it first */ 93 /* xor C[m] into checksum */ 94 for (x = 0; x < (int)ptlen; x++) { 95 ocb->checksum[x] ^= ct[x]; 96 } 97 } 98 99 /* C[m] = P[m] xor Y[m] */ 100 for (x = 0; x < (int)ptlen; x++) { 101 ct[x] = pt[x] ^ Y[x]; 102 } 103 104 if (mode == 0) { 105 /* encrypt mode */ 106 /* xor C[m] into checksum */ 107 for (x = 0; x < (int)ptlen; x++) { 108 ocb->checksum[x] ^= ct[x]; 109 } 110 } 111 112 /* xor Y[m] and Z[m] into checksum */ 113 for (x = 0; x < ocb->block_len; x++) { 114 ocb->checksum[x] ^= Y[x] ^ Z[x]; 115 } 116 117 /* encrypt checksum, er... tag!! */ 118 if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key)) != CRYPT_OK) { 119 goto error; 120 } 121 cipher_descriptor[ocb->cipher].done(&ocb->key); 122 123 /* now store it */ 124 for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { 125 tag[x] = X[x]; 126 } 127 *taglen = x; 128 129 #ifdef LTC_CLEAN_STACK 130 zeromem(X, MAXBLOCKSIZE); 131 zeromem(Y, MAXBLOCKSIZE); 132 zeromem(Z, MAXBLOCKSIZE); 133 zeromem(ocb, sizeof(*ocb)); 134 #endif 135 error: 136 XFREE(X); 137 XFREE(Y); 138 XFREE(Z); 139 140 return err; 141 } 142 143 #endif 144 145 146 /* $Source: /cvs/libtom/libtomcrypt/src/encauth/ocb/s_ocb_done.c,v $ */ 147 /* $Revision: 1.6 $ */ 148 /* $Date: 2006/03/31 14:15:35 $ */ 149