Single step kdf implementation
[openssl.git] / crypto / evp / kdf_lib.c
1 /*
2  * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2018, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include "internal/cryptlib.h"
14 #include <openssl/engine.h>
15 #include <openssl/evp.h>
16 #include <openssl/x509v3.h>
17 #include <openssl/kdf.h>
18 #include "internal/asn1_int.h"
19 #include "internal/evp_int.h"
20 #include "internal/numbers.h"
21 #include "evp_locl.h"
22
23 typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
24
25 /* This array needs to be in order of NIDs */
26 static const EVP_KDF_METHOD *standard_methods[] = {
27     &pbkdf2_kdf_meth,
28 #ifndef OPENSSL_NO_SCRYPT
29     &scrypt_kdf_meth,
30 #endif
31     &tls1_prf_kdf_meth,
32     &hkdf_kdf_meth,
33     &sshkdf_kdf_meth,
34     &ss_kdf_meth
35 };
36
37 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
38                            kmeth);
39
40 static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
41                      const EVP_KDF_METHOD *const *b)
42 {
43     return ((*a)->type - (*b)->type);
44 }
45
46 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
47                              kmeth);
48
49 static const EVP_KDF_METHOD *kdf_meth_find(int type)
50 {
51     EVP_KDF_METHOD tmp;
52     const EVP_KDF_METHOD *t = &tmp, **ret;
53
54     tmp.type = type;
55     ret = OBJ_bsearch_kmeth(&t, standard_methods,
56                             OSSL_NELEM(standard_methods));
57     if (ret == NULL || *ret == NULL)
58         return NULL;
59
60     return *ret;
61 }
62
63 EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
64 {
65     EVP_KDF_CTX *ret;
66     const EVP_KDF_METHOD *kmeth;
67
68     kmeth = kdf_meth_find(id);
69     if (kmeth == NULL) {
70         EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
71         return NULL;
72     }
73
74     ret = OPENSSL_zalloc(sizeof(*ret));
75     if (ret == NULL) {
76         EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
77         return NULL;
78     }
79
80     if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
81         EVP_KDF_CTX_free(ret);
82         return NULL;
83     }
84
85     ret->kmeth = kmeth;
86     return ret;
87 }
88
89 void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
90 {
91     if (ctx == NULL)
92         return;
93
94     ctx->kmeth->free(ctx->impl);
95     OPENSSL_free(ctx);
96 }
97
98 void EVP_KDF_reset(EVP_KDF_CTX *ctx)
99 {
100     if (ctx == NULL)
101         return;
102
103     if (ctx->kmeth->reset != NULL)
104         ctx->kmeth->reset(ctx->impl);
105 }
106
107 int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
108 {
109     int ret;
110     va_list args;
111
112     va_start(args, cmd);
113     ret = EVP_KDF_vctrl(ctx, cmd, args);
114     va_end(args);
115
116     if (ret == -2)
117         EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
118
119     return ret;
120 }
121
122 int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
123 {
124     if (ctx == NULL)
125         return 0;
126
127     return ctx->kmeth->ctrl(ctx->impl, cmd, args);
128 }
129
130 int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
131 {
132     int ret;
133
134     if (ctx == NULL)
135         return 0;
136
137     if (ctx->kmeth->ctrl_str == NULL) {
138         EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
139         return -2;
140     }
141
142     ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
143     if (ret == -2)
144         EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
145
146     return ret;
147 }
148
149 size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
150 {
151     if (ctx == NULL)
152         return 0;
153
154     if (ctx->kmeth->size == NULL)
155         return SIZE_MAX;
156
157     return ctx->kmeth->size(ctx->impl);
158 }
159
160 int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
161 {
162     if (ctx == NULL)
163         return 0;
164
165     return ctx->kmeth->derive(ctx->impl, key, keylen);
166 }
167