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