Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tomcrypt/src/encauth/ocb3/ocb3_encrypt_last.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 ocb3_encrypt_last.c
12
OCB implementation, internal helper, by Karel Miko
13
*/
14
#include "tomcrypt.h"
15
16
#ifdef LTC_OCB3_MODE
17
18
/**
19
Finish an OCB (encryption) stream
20
@param ocb The OCB state
21
@param pt The remaining plaintext
22
@param ptlen The length of the plaintext (octets)
23
@param ct [out] The output buffer
24
@return CRYPT_OK if successful
25
*/
26
int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct)
27
{
28
unsigned char iOffset_star[MAXBLOCKSIZE];
29
unsigned char iPad[MAXBLOCKSIZE];
30
int err, x, full_blocks, full_blocks_len, last_block_len;
31
32
LTC_ARGCHK(ocb != NULL);
33
if (pt == NULL) LTC_ARGCHK(ptlen == 0);
34
if (ptlen != 0) {
35
LTC_ARGCHK(pt != NULL);
36
LTC_ARGCHK(ct != NULL);
37
}
38
39
if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) {
40
goto LBL_ERR;
41
}
42
43
full_blocks = ptlen/ocb->block_len;
44
full_blocks_len = full_blocks * ocb->block_len;
45
last_block_len = ptlen - full_blocks_len;
46
47
/* process full blocks first */
48
if (full_blocks>0) {
49
if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) {
50
goto LBL_ERR;
51
}
52
}
53
54
/* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */
55
56
if (last_block_len>0) {
57
/* Offset_* = Offset_m xor L_* */
58
ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len);
59
60
/* Pad = ENCIPHER(K, Offset_*) */
61
if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) {
62
goto LBL_ERR;
63
}
64
65
/* C_* = P_* xor Pad[1..bitlen(P_*)] */
66
ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len);
67
68
/* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
69
ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len);
70
for(x=last_block_len; x<ocb->block_len; x++) {
71
if (x == last_block_len)
72
ocb->checksum[x] ^= 0x80;
73
else
74
ocb->checksum[x] ^= 0x00;
75
}
76
77
/* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */
78
/* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */
79
for(x=0; x<ocb->block_len; x++) {
80
ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x];
81
}
82
if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
83
goto LBL_ERR;
84
}
85
}
86
else {
87
/* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */
88
/* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */
89
for(x=0; x<ocb->block_len; x++) {
90
ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x];
91
}
92
if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) {
93
goto LBL_ERR;
94
}
95
}
96
97
err = CRYPT_OK;
98
99
LBL_ERR:
100
#ifdef LTC_CLEAN_STACK
101
zeromem(iOffset_star, MAXBLOCKSIZE);
102
zeromem(iPad, MAXBLOCKSIZE);
103
#endif
104
105
return err;
106
}
107
108
#endif
109
110