Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/tomcrypt/src/misc/pkcs5/pkcs_5_1.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
#include "tomcrypt.h"
10
11
/**
12
@file pkcs_5_1.c
13
PKCS #5, Algorithm #1, Tom St Denis
14
*/
15
#ifdef LTC_PKCS_5
16
/**
17
Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode.
18
19
PKCS#5 v1 specifies that the output key length can be no larger than
20
the hash output length. OpenSSL unilaterally extended that by repeating
21
the hash process on a block-by-block basis for as long as needed to make
22
bigger keys. If you want to be compatible with KDF for e.g. "openssl enc",
23
you'll want that.
24
25
If you want strict PKCS behavior, turn openssl_compat off. Or (more
26
likely), use one of the convenience functions below.
27
28
@param password The password (or key)
29
@param password_len The length of the password (octet)
30
@param salt The salt (or nonce) which is 8 octets long
31
@param iteration_count The PKCS #5 v1 iteration count
32
@param hash_idx The index of the hash desired
33
@param out [out] The destination for this algorithm
34
@param outlen [in/out] The max size and resulting size of the algorithm output
35
@param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL
36
@return CRYPT_OK if successful
37
*/
38
static int _pkcs_5_alg1_common(const unsigned char *password,
39
unsigned long password_len,
40
const unsigned char *salt,
41
int iteration_count, int hash_idx,
42
unsigned char *out, unsigned long *outlen,
43
int openssl_compat)
44
{
45
int err;
46
unsigned long x;
47
hash_state *md;
48
unsigned char *buf;
49
/* Storage vars in case we need to support > hashsize (OpenSSL compat) */
50
unsigned long block = 0, iter;
51
/* How many bytes to put in the outbut buffer (convenience calc) */
52
unsigned long outidx = 0, nb = 0;
53
54
LTC_ARGCHK(password != NULL);
55
LTC_ARGCHK(salt != NULL);
56
LTC_ARGCHK(out != NULL);
57
LTC_ARGCHK(outlen != NULL);
58
59
/* test hash IDX */
60
if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
61
return err;
62
}
63
64
/* allocate memory */
65
md = XMALLOC(sizeof(hash_state));
66
buf = XMALLOC(MAXBLOCKSIZE);
67
if (md == NULL || buf == NULL) {
68
if (md != NULL) {
69
XFREE(md);
70
}
71
if (buf != NULL) {
72
XFREE(buf);
73
}
74
return CRYPT_MEM;
75
}
76
77
while(block * hash_descriptor[hash_idx].hashsize < *outlen) {
78
79
/* hash initial (maybe previous hash) + password + salt */
80
if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) {
81
goto LBL_ERR;
82
}
83
/* in OpenSSL mode, we first hash the previous result for blocks 2-n */
84
if (openssl_compat && block) {
85
if ((err = hash_descriptor[hash_idx].process(md, buf, hash_descriptor[hash_idx].hashsize)) != CRYPT_OK) {
86
goto LBL_ERR;
87
}
88
}
89
if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) {
90
goto LBL_ERR;
91
}
92
if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) {
93
goto LBL_ERR;
94
}
95
if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) {
96
goto LBL_ERR;
97
}
98
99
iter = iteration_count;
100
while (--iter) {
101
/* code goes here. */
102
x = MAXBLOCKSIZE;
103
if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) {
104
goto LBL_ERR;
105
}
106
}
107
108
/* limit the size of the copy to however many bytes we have left in
109
the output buffer (and how many bytes we have to copy) */
110
outidx = block*hash_descriptor[hash_idx].hashsize;
111
nb = hash_descriptor[hash_idx].hashsize;
112
if(outidx+nb > *outlen)
113
nb = *outlen - outidx;
114
if(nb > 0)
115
XMEMCPY(out+outidx, buf, nb);
116
117
block++;
118
if (!openssl_compat)
119
break;
120
}
121
/* In strict mode, we always return the hashsize, in compat we filled it
122
as much as was requested, so we leave it alone. */
123
if(!openssl_compat)
124
*outlen = hash_descriptor[hash_idx].hashsize;
125
126
err = CRYPT_OK;
127
LBL_ERR:
128
#ifdef LTC_CLEAN_STACK
129
zeromem(buf, MAXBLOCKSIZE);
130
zeromem(md, sizeof(hash_state));
131
#endif
132
133
XFREE(buf);
134
XFREE(md);
135
136
return err;
137
}
138
139
/**
140
Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension)
141
@param password The password (or key)
142
@param password_len The length of the password (octet)
143
@param salt The salt (or nonce) which is 8 octets long
144
@param iteration_count The PKCS #5 v1 iteration count
145
@param hash_idx The index of the hash desired
146
@param out [out] The destination for this algorithm
147
@param outlen [in/out] The max size and resulting size of the algorithm output
148
@return CRYPT_OK if successful
149
*/
150
int pkcs_5_alg1(const unsigned char *password, unsigned long password_len,
151
const unsigned char *salt,
152
int iteration_count, int hash_idx,
153
unsigned char *out, unsigned long *outlen)
154
{
155
return _pkcs_5_alg1_common(password, password_len, salt, iteration_count,
156
hash_idx, out, outlen, 0);
157
}
158
159
/**
160
Execute PKCS #5 v1 - OpenSSL-extension-compatible mode
161
162
Use this one if you need to derive keys as "openssl enc" does by default.
163
OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1.
164
@param password The password (or key)
165
@param password_len The length of the password (octet)
166
@param salt The salt (or nonce) which is 8 octets long
167
@param iteration_count The PKCS #5 v1 iteration count
168
@param hash_idx The index of the hash desired
169
@param out [out] The destination for this algorithm
170
@param outlen [in/out] The max size and resulting size of the algorithm output
171
@return CRYPT_OK if successful
172
*/
173
int pkcs_5_alg1_openssl(const unsigned char *password,
174
unsigned long password_len,
175
const unsigned char *salt,
176
int iteration_count, int hash_idx,
177
unsigned char *out, unsigned long *outlen)
178
{
179
return _pkcs_5_alg1_common(password, password_len, salt, iteration_count,
180
hash_idx, out, outlen, 1);
181
}
182
183
#endif
184
185