Mercurial > dovecot > core-2.2
annotate src/lib/pkcs5.c @ 22664:fea53c2725c0
director: Fix director_max_parallel_moves/kicks type
Should be uint, not time.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 09 Nov 2017 12:24:16 +0200 |
parents | 2e2563132d5f |
children | cb108f786fb4 |
rev | line source |
---|---|
21390
2e2563132d5f
Updated copyright notices to include the year 2017.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents:
21264
diff
changeset
|
1 /* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */ |
21264
8f33680c6722
global: Added missing copyright notices.
Stephan Bosch <stephan.bosch@dovecot.fi>
parents:
20252
diff
changeset
|
2 |
20252 | 3 #include "lib.h" |
4 #include "buffer.h" | |
5 #include "hash-method.h" | |
6 #include "hmac.h" | |
7 #include "pkcs5.h" | |
8 | |
9 #include <stdint.h> | |
10 #include <arpa/inet.h> | |
11 | |
12 static | |
13 int pkcs5_pbkdf1(const struct hash_method *hash, | |
14 const unsigned char *password, size_t password_len, | |
15 const unsigned char *salt, size_t salt_len, | |
16 unsigned int iter, uint32_t length, | |
17 buffer_t *result) | |
18 { | |
19 if (length < 1 || | |
20 length > hash->digest_size) return -1; | |
21 if (iter < 1) return -1; | |
22 | |
23 unsigned char dk[hash->digest_size]; | |
24 unsigned char ctx[hash->context_size]; | |
25 | |
26 hash->init(ctx); | |
27 hash->loop(ctx, password, password_len); | |
28 hash->loop(ctx, salt, salt_len); | |
29 hash->result(ctx, dk); | |
30 length--; | |
31 | |
32 for(;length>0;length--) { | |
33 hash->init(ctx); | |
34 hash->loop(ctx, dk, hash->digest_size); | |
35 hash->result(ctx, dk); | |
36 } | |
37 | |
38 buffer_append(result, dk, hash->digest_size); | |
39 | |
40 return 0; | |
41 } | |
42 | |
43 static | |
44 int pkcs5_pbkdf2(const struct hash_method *hash, | |
45 const unsigned char *password, size_t password_len, | |
46 const unsigned char *salt, size_t salt_len, | |
47 unsigned int iter, uint32_t length, | |
48 buffer_t *result) | |
49 { | |
50 if (length < 1 || iter < 1) return -1; | |
51 | |
52 size_t l = (length + hash->digest_size - 1)/hash->digest_size; /* same as ceil(length/hash->digest_size) */ | |
53 unsigned char dk[l * hash->digest_size]; | |
54 unsigned char *block; | |
55 struct hmac_context hctx; | |
56 unsigned int c,i,t; | |
57 unsigned char U_c[hash->digest_size]; | |
58 | |
59 for(t = 0; t < l; t++) { | |
60 block = &(dk[t*hash->digest_size]); | |
61 /* U_1 = PRF(Password, Salt|| INT_BE32(Block_Number)) */ | |
62 c = htonl(t+1); | |
63 hmac_init(&hctx, password, password_len, hash); | |
64 hmac_update(&hctx, salt, salt_len); | |
65 hmac_update(&hctx, &c, sizeof(c)); | |
66 hmac_final(&hctx, U_c); | |
67 /* block = U_1 ^ .. ^ U_iter */ | |
68 memcpy(block, U_c, hash->digest_size); | |
69 /* U_c = PRF(Password, U_c-1) */ | |
70 for(c = 1; c < iter; c++) { | |
71 hmac_init(&hctx, password, password_len, hash); | |
72 hmac_update(&hctx, U_c, hash->digest_size); | |
73 hmac_final(&hctx, U_c); | |
74 for(i = 0; i < hash->digest_size; i++) | |
75 block[i] ^= U_c[i]; | |
76 } | |
77 } | |
78 | |
79 buffer_append(result, dk, length); | |
80 | |
81 return 0; | |
82 } | |
83 | |
84 int pkcs5_pbkdf(enum pkcs5_pbkdf_mode mode, const struct hash_method *hash, | |
85 const unsigned char *password, size_t password_len, | |
86 const unsigned char *salt, size_t salt_len, | |
87 unsigned int iterations, uint32_t dk_len, | |
88 buffer_t *result) | |
89 { | |
90 if (mode == PKCS5_PBKDF1) | |
91 return pkcs5_pbkdf1(hash,password,password_len, | |
92 salt,salt_len,iterations,dk_len,result); | |
93 else if (mode == PKCS5_PBKDF2) | |
94 return pkcs5_pbkdf2(hash,password,password_len, | |
95 salt,salt_len,iterations,dk_len,result); | |
96 i_unreached(); | |
97 } |