• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2006-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 <openssl/evp.h>
11
12#include <openssl/err.h>
13
14#include "../../evp/internal.h"
15#include "../delocate.h"
16#include "../digest/internal.h"
17#include "../service_indicator/internal.h"
18
19
20enum evp_sign_verify_t {
21  evp_sign,
22  evp_verify,
23};
24
25DEFINE_LOCAL_DATA(struct evp_md_pctx_ops, md_pctx_ops) {
26  out->free = EVP_PKEY_CTX_free;
27  out->dup = EVP_PKEY_CTX_dup;
28}
29
30static int uses_prehash(EVP_MD_CTX *ctx, enum evp_sign_verify_t op) {
31  return (op == evp_sign) ? (ctx->pctx->pmeth->sign != NULL)
32                          : (ctx->pctx->pmeth->verify != NULL);
33}
34
35static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
36                          const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
37                          enum evp_sign_verify_t op) {
38  if (ctx->pctx == NULL) {
39    ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
40  }
41  if (ctx->pctx == NULL) {
42    return 0;
43  }
44  ctx->pctx_ops = md_pctx_ops();
45
46  if (op == evp_verify) {
47    if (!EVP_PKEY_verify_init(ctx->pctx)) {
48      return 0;
49    }
50  } else {
51    if (!EVP_PKEY_sign_init(ctx->pctx)) {
52      return 0;
53    }
54  }
55
56  if (type != NULL &&
57      !EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
58    return 0;
59  }
60
61  if (uses_prehash(ctx, op)) {
62    if (type == NULL) {
63      OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
64      return 0;
65    }
66    if (!EVP_DigestInit_ex(ctx, type, e)) {
67      return 0;
68    }
69  }
70
71  if (pctx) {
72    *pctx = ctx->pctx;
73  }
74  return 1;
75}
76
77int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
78                       ENGINE *e, EVP_PKEY *pkey) {
79  return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign);
80}
81
82int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
83                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) {
84  return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify);
85}
86
87int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
88  if (!uses_prehash(ctx, evp_sign)) {
89    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
90    return 0;
91  }
92
93  return EVP_DigestUpdate(ctx, data, len);
94}
95
96int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
97  if (!uses_prehash(ctx, evp_verify)) {
98    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
99    return 0;
100  }
101
102  return EVP_DigestUpdate(ctx, data, len);
103}
104
105int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
106                        size_t *out_sig_len) {
107  if (!uses_prehash(ctx, evp_sign)) {
108    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
109    return 0;
110  }
111
112  if (out_sig) {
113    EVP_MD_CTX tmp_ctx;
114    int ret;
115    uint8_t md[EVP_MAX_MD_SIZE];
116    unsigned int mdlen;
117
118    FIPS_service_indicator_lock_state();
119    EVP_MD_CTX_init(&tmp_ctx);
120    ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
121          EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
122          EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
123    EVP_MD_CTX_cleanup(&tmp_ctx);
124    FIPS_service_indicator_unlock_state();
125
126    if (ret) {
127      EVP_DigestSign_verify_service_indicator(ctx);
128    }
129
130    return ret;
131  } else {
132    size_t s = EVP_MD_size(ctx->digest);
133    return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
134  }
135}
136
137int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
138                          size_t sig_len) {
139  if (!uses_prehash(ctx, evp_verify)) {
140    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
141    return 0;
142  }
143
144  EVP_MD_CTX tmp_ctx;
145  int ret;
146  uint8_t md[EVP_MAX_MD_SIZE];
147  unsigned int mdlen;
148
149  FIPS_service_indicator_lock_state();
150  EVP_MD_CTX_init(&tmp_ctx);
151  ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
152        EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
153        EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
154  FIPS_service_indicator_unlock_state();
155  EVP_MD_CTX_cleanup(&tmp_ctx);
156
157  if (ret) {
158    EVP_DigestVerify_verify_service_indicator(ctx);
159  }
160
161  return ret;
162}
163
164int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
165                   const uint8_t *data, size_t data_len) {
166  FIPS_service_indicator_lock_state();
167  int ret = 0;
168
169  if (uses_prehash(ctx, evp_sign)) {
170    // If |out_sig| is NULL, the caller is only querying the maximum output
171    // length. |data| should only be incorporated in the final call.
172    if (out_sig != NULL &&
173        !EVP_DigestSignUpdate(ctx, data, data_len)) {
174      goto end;
175    }
176
177    ret = EVP_DigestSignFinal(ctx, out_sig, out_sig_len);
178    goto end;
179  }
180
181  if (ctx->pctx->pmeth->sign_message == NULL) {
182    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
183    goto end;
184  }
185
186  ret = ctx->pctx->pmeth->sign_message(ctx->pctx, out_sig, out_sig_len, data,
187                                       data_len);
188
189end:
190  FIPS_service_indicator_unlock_state();
191  if (ret) {
192    EVP_DigestSign_verify_service_indicator(ctx);
193  }
194  return ret;
195}
196
197int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
198                     const uint8_t *data, size_t len) {
199  FIPS_service_indicator_lock_state();
200  int ret = 0;
201
202  if (uses_prehash(ctx, evp_verify)) {
203    ret = EVP_DigestVerifyUpdate(ctx, data, len) &&
204          EVP_DigestVerifyFinal(ctx, sig, sig_len);
205    goto end;
206  }
207
208  if (ctx->pctx->pmeth->verify_message == NULL) {
209    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
210    goto end;
211  }
212
213  ret = ctx->pctx->pmeth->verify_message(ctx->pctx, sig, sig_len, data, len);
214
215end:
216  FIPS_service_indicator_unlock_state();
217  if (ret) {
218    EVP_DigestVerify_verify_service_indicator(ctx);
219  }
220  return ret;
221}
222