1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h>
11e1051a39Sopenharmony_ci#include <openssl/core_names.h>
12e1051a39Sopenharmony_ci#include <openssl/params.h>
13e1051a39Sopenharmony_ci#include <openssl/evp.h>
14e1051a39Sopenharmony_ci#include <openssl/err.h>
15e1051a39Sopenharmony_ci#include <openssl/proverr.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include "crypto/poly1305.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci#include "prov/implementations.h"
20e1051a39Sopenharmony_ci#include "prov/providercommon.h"
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_ci/*
23e1051a39Sopenharmony_ci * Forward declaration of everything implemented here.  This is not strictly
24e1051a39Sopenharmony_ci * necessary for the compiler, but provides an assurance that the signatures
25e1051a39Sopenharmony_ci * of the functions in the dispatch table are correct.
26e1051a39Sopenharmony_ci */
27e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_newctx_fn poly1305_new;
28e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_dupctx_fn poly1305_dup;
29e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_freectx_fn poly1305_free;
30e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_gettable_params_fn poly1305_gettable_params;
31e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_get_params_fn poly1305_get_params;
32e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_settable_ctx_params_fn poly1305_settable_ctx_params;
33e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_set_ctx_params_fn poly1305_set_ctx_params;
34e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_init_fn poly1305_init;
35e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_update_fn poly1305_update;
36e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_final_fn poly1305_final;
37e1051a39Sopenharmony_ci
38e1051a39Sopenharmony_cistruct poly1305_data_st {
39e1051a39Sopenharmony_ci    void *provctx;
40e1051a39Sopenharmony_ci    int updated;
41e1051a39Sopenharmony_ci    POLY1305 poly1305;           /* Poly1305 data */
42e1051a39Sopenharmony_ci};
43e1051a39Sopenharmony_ci
44e1051a39Sopenharmony_cistatic void *poly1305_new(void *provctx)
45e1051a39Sopenharmony_ci{
46e1051a39Sopenharmony_ci    struct poly1305_data_st *ctx;
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
49e1051a39Sopenharmony_ci        return NULL;
50e1051a39Sopenharmony_ci    ctx = OPENSSL_zalloc(sizeof(*ctx));
51e1051a39Sopenharmony_ci    if (ctx != NULL)
52e1051a39Sopenharmony_ci        ctx->provctx = provctx;
53e1051a39Sopenharmony_ci    return ctx;
54e1051a39Sopenharmony_ci}
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_cistatic void poly1305_free(void *vmacctx)
57e1051a39Sopenharmony_ci{
58e1051a39Sopenharmony_ci    OPENSSL_free(vmacctx);
59e1051a39Sopenharmony_ci}
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_cistatic void *poly1305_dup(void *vsrc)
62e1051a39Sopenharmony_ci{
63e1051a39Sopenharmony_ci    struct poly1305_data_st *src = vsrc;
64e1051a39Sopenharmony_ci    struct poly1305_data_st *dst;
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
67e1051a39Sopenharmony_ci        return NULL;
68e1051a39Sopenharmony_ci    dst = OPENSSL_malloc(sizeof(*dst));
69e1051a39Sopenharmony_ci    if (dst == NULL)
70e1051a39Sopenharmony_ci        return NULL;
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci    *dst = *src;
73e1051a39Sopenharmony_ci    return dst;
74e1051a39Sopenharmony_ci}
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_cistatic size_t poly1305_size(void)
77e1051a39Sopenharmony_ci{
78e1051a39Sopenharmony_ci    return POLY1305_DIGEST_SIZE;
79e1051a39Sopenharmony_ci}
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_cistatic int poly1305_setkey(struct poly1305_data_st *ctx,
82e1051a39Sopenharmony_ci                           const unsigned char *key, size_t keylen)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    if (keylen != POLY1305_KEY_SIZE) {
85e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
86e1051a39Sopenharmony_ci        return 0;
87e1051a39Sopenharmony_ci    }
88e1051a39Sopenharmony_ci    Poly1305_Init(&ctx->poly1305, key);
89e1051a39Sopenharmony_ci    ctx->updated = 0;
90e1051a39Sopenharmony_ci    return 1;
91e1051a39Sopenharmony_ci}
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_cistatic int poly1305_init(void *vmacctx, const unsigned char *key,
94e1051a39Sopenharmony_ci                         size_t keylen, const OSSL_PARAM params[])
95e1051a39Sopenharmony_ci{
96e1051a39Sopenharmony_ci    struct poly1305_data_st *ctx = vmacctx;
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_ci    /* initialize the context in MAC_ctrl function */
99e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || !poly1305_set_ctx_params(ctx, params))
100e1051a39Sopenharmony_ci        return 0;
101e1051a39Sopenharmony_ci    if (key != NULL)
102e1051a39Sopenharmony_ci        return poly1305_setkey(ctx, key, keylen);
103e1051a39Sopenharmony_ci    /* no reinitialization of context with the same key is allowed */
104e1051a39Sopenharmony_ci    return ctx->updated == 0;
105e1051a39Sopenharmony_ci}
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_cistatic int poly1305_update(void *vmacctx, const unsigned char *data,
108e1051a39Sopenharmony_ci                       size_t datalen)
109e1051a39Sopenharmony_ci{
110e1051a39Sopenharmony_ci    struct poly1305_data_st *ctx = vmacctx;
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci    ctx->updated = 1;
113e1051a39Sopenharmony_ci    if (datalen == 0)
114e1051a39Sopenharmony_ci        return 1;
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    /* poly1305 has nothing to return in its update function */
117e1051a39Sopenharmony_ci    Poly1305_Update(&ctx->poly1305, data, datalen);
118e1051a39Sopenharmony_ci    return 1;
119e1051a39Sopenharmony_ci}
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_cistatic int poly1305_final(void *vmacctx, unsigned char *out, size_t *outl,
122e1051a39Sopenharmony_ci                          size_t outsize)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    struct poly1305_data_st *ctx = vmacctx;
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
127e1051a39Sopenharmony_ci        return 0;
128e1051a39Sopenharmony_ci    ctx->updated = 1;
129e1051a39Sopenharmony_ci    Poly1305_Final(&ctx->poly1305, out);
130e1051a39Sopenharmony_ci    *outl = poly1305_size();
131e1051a39Sopenharmony_ci    return 1;
132e1051a39Sopenharmony_ci}
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_cistatic const OSSL_PARAM known_gettable_params[] = {
135e1051a39Sopenharmony_ci    OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
136e1051a39Sopenharmony_ci    OSSL_PARAM_END
137e1051a39Sopenharmony_ci};
138e1051a39Sopenharmony_cistatic const OSSL_PARAM *poly1305_gettable_params(void *provctx)
139e1051a39Sopenharmony_ci{
140e1051a39Sopenharmony_ci    return known_gettable_params;
141e1051a39Sopenharmony_ci}
142e1051a39Sopenharmony_ci
143e1051a39Sopenharmony_cistatic int poly1305_get_params(OSSL_PARAM params[])
144e1051a39Sopenharmony_ci{
145e1051a39Sopenharmony_ci    OSSL_PARAM *p;
146e1051a39Sopenharmony_ci
147e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL)
148e1051a39Sopenharmony_ci        return OSSL_PARAM_set_size_t(p, poly1305_size());
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    return 1;
151e1051a39Sopenharmony_ci}
152e1051a39Sopenharmony_ci
153e1051a39Sopenharmony_cistatic const OSSL_PARAM known_settable_ctx_params[] = {
154e1051a39Sopenharmony_ci    OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0),
155e1051a39Sopenharmony_ci    OSSL_PARAM_END
156e1051a39Sopenharmony_ci};
157e1051a39Sopenharmony_cistatic const OSSL_PARAM *poly1305_settable_ctx_params(ossl_unused void *ctx,
158e1051a39Sopenharmony_ci                                                      ossl_unused void *provctx)
159e1051a39Sopenharmony_ci{
160e1051a39Sopenharmony_ci    return known_settable_ctx_params;
161e1051a39Sopenharmony_ci}
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_cistatic int poly1305_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
164e1051a39Sopenharmony_ci{
165e1051a39Sopenharmony_ci    struct poly1305_data_st *ctx = vmacctx;
166e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL
169e1051a39Sopenharmony_ci            && !poly1305_setkey(ctx, p->data, p->data_size))
170e1051a39Sopenharmony_ci        return 0;
171e1051a39Sopenharmony_ci    return 1;
172e1051a39Sopenharmony_ci}
173e1051a39Sopenharmony_ci
174e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_poly1305_functions[] = {
175e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))poly1305_new },
176e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))poly1305_dup },
177e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_FREECTX, (void (*)(void))poly1305_free },
178e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_INIT, (void (*)(void))poly1305_init },
179e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_UPDATE, (void (*)(void))poly1305_update },
180e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_FINAL, (void (*)(void))poly1305_final },
181e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))poly1305_gettable_params },
182e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))poly1305_get_params },
183e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
184e1051a39Sopenharmony_ci      (void (*)(void))poly1305_settable_ctx_params },
185e1051a39Sopenharmony_ci    { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))poly1305_set_ctx_params },
186e1051a39Sopenharmony_ci    { 0, NULL }
187e1051a39Sopenharmony_ci};
188