1 // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <openssl/cipher.h>
16 
17 #include <assert.h>
18 
19 #include <openssl/digest.h>
20 #include <openssl/mem.h>
21 
22 
EVP_BytesToKey(const EVP_CIPHER * type,const EVP_MD * md,const uint8_t salt[8],const uint8_t * data,size_t data_len,unsigned count,uint8_t * key,uint8_t * iv)23 int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
24                    const uint8_t salt[8], const uint8_t *data, size_t data_len,
25                    unsigned count, uint8_t *key, uint8_t *iv) {
26   uint8_t md_buf[EVP_MAX_MD_SIZE];
27   unsigned addmd = 0;
28   unsigned mds = 0, i;
29   int rv = 0;
30 
31   unsigned nkey = EVP_CIPHER_key_length(type);
32   unsigned niv = EVP_CIPHER_iv_length(type);
33 
34   assert(nkey <= EVP_MAX_KEY_LENGTH);
35   assert(niv <= EVP_MAX_IV_LENGTH);
36 
37   if (data == nullptr) {
38     return nkey;
39   }
40 
41   bssl::ScopedEVP_MD_CTX c;
42   for (;;) {
43     if (!EVP_DigestInit_ex(c.get(), md, nullptr)) {
44       goto err;
45     }
46     if (addmd++) {
47       if (!EVP_DigestUpdate(c.get(), md_buf, mds)) {
48         goto err;
49       }
50     }
51     if (!EVP_DigestUpdate(c.get(), data, data_len)) {
52       goto err;
53     }
54     if (salt != nullptr) {
55       if (!EVP_DigestUpdate(c.get(), salt, 8)) {
56         goto err;
57       }
58     }
59     if (!EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
60       goto err;
61     }
62 
63     for (i = 1; i < count; i++) {
64       if (!EVP_DigestInit_ex(c.get(), md, nullptr) ||
65           !EVP_DigestUpdate(c.get(), md_buf, mds) ||
66           !EVP_DigestFinal_ex(c.get(), md_buf, &mds)) {
67         goto err;
68       }
69     }
70 
71     i = 0;
72     if (nkey) {
73       for (;;) {
74         if (nkey == 0 || i == mds) {
75           break;
76         }
77         if (key != nullptr) {
78           *(key++) = md_buf[i];
79         }
80         nkey--;
81         i++;
82       }
83     }
84 
85     if (niv && i != mds) {
86       for (;;) {
87         if (niv == 0 || i == mds) {
88           break;
89         }
90         if (iv != nullptr) {
91           *(iv++) = md_buf[i];
92         }
93         niv--;
94         i++;
95       }
96     }
97     if (nkey == 0 && niv == 0) {
98       break;
99     }
100   }
101   rv = EVP_CIPHER_key_length(type);
102 
103 err:
104   OPENSSL_cleanse(md_buf, EVP_MAX_MD_SIZE);
105   return rv;
106 }
107