check return values for EVP_Digest*() APIs
[openssl.git] / crypto / ec / ecdh_kdf.c
1 /*
2  * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <string.h>
11 #include <openssl/ec.h>
12 #include <openssl/evp.h>
13
14 /* Key derivation function from X9.62/SECG */
15 /* Way more than we will ever need */
16 #define ECDH_KDF_MAX    (1 << 30)
17
18 int ECDH_KDF_X9_62(unsigned char *out, size_t outlen,
19                    const unsigned char *Z, size_t Zlen,
20                    const unsigned char *sinfo, size_t sinfolen,
21                    const EVP_MD *md)
22 {
23     EVP_MD_CTX *mctx = NULL;
24     int rv = 0;
25     unsigned int i;
26     size_t mdlen;
27     unsigned char ctr[4];
28     if (sinfolen > ECDH_KDF_MAX || outlen > ECDH_KDF_MAX
29         || Zlen > ECDH_KDF_MAX)
30         return 0;
31     mctx = EVP_MD_CTX_new();
32     if (mctx == NULL)
33         return 0;
34     mdlen = EVP_MD_size(md);
35     for (i = 1;; i++) {
36         unsigned char mtmp[EVP_MAX_MD_SIZE];
37         if (!EVP_DigestInit_ex(mctx, md, NULL))
38             goto err;
39         ctr[3] = i & 0xFF;
40         ctr[2] = (i >> 8) & 0xFF;
41         ctr[1] = (i >> 16) & 0xFF;
42         ctr[0] = (i >> 24) & 0xFF;
43         if (!EVP_DigestUpdate(mctx, Z, Zlen))
44             goto err;
45         if (!EVP_DigestUpdate(mctx, ctr, sizeof(ctr)))
46             goto err;
47         if (!EVP_DigestUpdate(mctx, sinfo, sinfolen))
48             goto err;
49         if (outlen >= mdlen) {
50             if (!EVP_DigestFinal(mctx, out, NULL))
51                 goto err;
52             outlen -= mdlen;
53             if (outlen == 0)
54                 break;
55             out += mdlen;
56         } else {
57             if (!EVP_DigestFinal(mctx, mtmp, NULL))
58                 goto err;
59             memcpy(out, mtmp, outlen);
60             OPENSSL_cleanse(mtmp, mdlen);
61             break;
62         }
63     }
64     rv = 1;
65  err:
66     EVP_MD_CTX_free(mctx);
67     return rv;
68 }