]>
Commit | Line | Data |
---|---|---|
62867571 RS |
1 | /* |
2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | |
0f113f3e | 3 | * |
62867571 RS |
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 | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <errno.h> | |
b39fc560 | 12 | #include "internal/cryptlib.h" |
ec577822 BM |
13 | #include <openssl/buffer.h> |
14 | #include <openssl/evp.h> | |
ab0a14bb | 15 | #include "internal/evp_int.h" |
77a01145 | 16 | #include "evp_locl.h" |
a146ae55 | 17 | #include "internal/bio.h" |
d02b48c6 | 18 | |
0f113f3e MC |
19 | /* |
20 | * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest | |
21 | */ | |
d02b48c6 | 22 | |
0e1c0612 UM |
23 | static int md_write(BIO *h, char const *buf, int num); |
24 | static int md_read(BIO *h, char *buf, int size); | |
0f113f3e MC |
25 | /* |
26 | * static int md_puts(BIO *h, const char *str); | |
27 | */ | |
0e1c0612 UM |
28 | static int md_gets(BIO *h, char *str, int size); |
29 | static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); | |
d02b48c6 RE |
30 | static int md_new(BIO *h); |
31 | static int md_free(BIO *data); | |
0f113f3e | 32 | static long md_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); |
d3442bc7 | 33 | |
04f6b0fd | 34 | static const BIO_METHOD methods_md = { |
0f113f3e MC |
35 | BIO_TYPE_MD, "message digest", |
36 | md_write, | |
37 | md_read, | |
38 | NULL, /* md_puts, */ | |
39 | md_gets, | |
40 | md_ctrl, | |
41 | md_new, | |
42 | md_free, | |
43 | md_callback_ctrl, | |
44 | }; | |
d02b48c6 | 45 | |
04f6b0fd | 46 | const BIO_METHOD *BIO_f_md(void) |
0f113f3e MC |
47 | { |
48 | return (&methods_md); | |
49 | } | |
d02b48c6 | 50 | |
6b691a5c | 51 | static int md_new(BIO *bi) |
0f113f3e MC |
52 | { |
53 | EVP_MD_CTX *ctx; | |
d02b48c6 | 54 | |
bfb0641f | 55 | ctx = EVP_MD_CTX_new(); |
0f113f3e MC |
56 | if (ctx == NULL) |
57 | return (0); | |
d02b48c6 | 58 | |
a146ae55 MC |
59 | BIO_set_init(bi, 1); |
60 | BIO_set_data(bi, ctx); | |
61 | ||
62 | return 1; | |
0f113f3e | 63 | } |
d02b48c6 | 64 | |
6b691a5c | 65 | static int md_free(BIO *a) |
0f113f3e MC |
66 | { |
67 | if (a == NULL) | |
68 | return (0); | |
a146ae55 MC |
69 | EVP_MD_CTX_free(BIO_get_data(a)); |
70 | BIO_set_data(a, NULL); | |
71 | BIO_set_init(a, 0); | |
72 | ||
73 | return 1; | |
0f113f3e MC |
74 | } |
75 | ||
6b691a5c | 76 | static int md_read(BIO *b, char *out, int outl) |
0f113f3e MC |
77 | { |
78 | int ret = 0; | |
79 | EVP_MD_CTX *ctx; | |
a146ae55 | 80 | BIO *next; |
d02b48c6 | 81 | |
0f113f3e MC |
82 | if (out == NULL) |
83 | return (0); | |
d02b48c6 | 84 | |
a146ae55 MC |
85 | ctx = BIO_get_data(b); |
86 | next = BIO_next(b); | |
87 | ||
88 | if ((ctx == NULL) || (next == NULL)) | |
0f113f3e | 89 | return (0); |
d02b48c6 | 90 | |
a146ae55 MC |
91 | ret = BIO_read(next, out, outl); |
92 | if (BIO_get_init(b)) { | |
0f113f3e MC |
93 | if (ret > 0) { |
94 | if (EVP_DigestUpdate(ctx, (unsigned char *)out, | |
95 | (unsigned int)ret) <= 0) | |
96 | return (-1); | |
97 | } | |
98 | } | |
99 | BIO_clear_retry_flags(b); | |
100 | BIO_copy_next_retry(b); | |
101 | return (ret); | |
102 | } | |
d02b48c6 | 103 | |
0e1c0612 | 104 | static int md_write(BIO *b, const char *in, int inl) |
0f113f3e MC |
105 | { |
106 | int ret = 0; | |
107 | EVP_MD_CTX *ctx; | |
a146ae55 | 108 | BIO *next; |
d02b48c6 | 109 | |
0f113f3e | 110 | if ((in == NULL) || (inl <= 0)) |
a146ae55 | 111 | return 0; |
d02b48c6 | 112 | |
a146ae55 MC |
113 | ctx = BIO_get_data(b); |
114 | next = BIO_next(b); | |
115 | if ((ctx != NULL) && (next != NULL)) | |
116 | ret = BIO_write(next, in, inl); | |
117 | ||
118 | if (BIO_get_init(b)) { | |
0f113f3e MC |
119 | if (ret > 0) { |
120 | if (!EVP_DigestUpdate(ctx, (const unsigned char *)in, | |
121 | (unsigned int)ret)) { | |
122 | BIO_clear_retry_flags(b); | |
123 | return 0; | |
124 | } | |
125 | } | |
126 | } | |
a146ae55 | 127 | if (next != NULL) { |
0f113f3e MC |
128 | BIO_clear_retry_flags(b); |
129 | BIO_copy_next_retry(b); | |
130 | } | |
a146ae55 | 131 | return ret; |
0f113f3e | 132 | } |
d02b48c6 | 133 | |
0e1c0612 | 134 | static long md_ctrl(BIO *b, int cmd, long num, void *ptr) |
0f113f3e MC |
135 | { |
136 | EVP_MD_CTX *ctx, *dctx, **pctx; | |
137 | const EVP_MD **ppmd; | |
138 | EVP_MD *md; | |
139 | long ret = 1; | |
a146ae55 | 140 | BIO *dbio, *next; |
d02b48c6 | 141 | |
a146ae55 MC |
142 | |
143 | ctx = BIO_get_data(b); | |
144 | next = BIO_next(b); | |
d02b48c6 | 145 | |
0f113f3e MC |
146 | switch (cmd) { |
147 | case BIO_CTRL_RESET: | |
a146ae55 | 148 | if (BIO_get_init(b)) |
0f113f3e MC |
149 | ret = EVP_DigestInit_ex(ctx, ctx->digest, NULL); |
150 | else | |
151 | ret = 0; | |
152 | if (ret > 0) | |
a146ae55 | 153 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
154 | break; |
155 | case BIO_C_GET_MD: | |
a146ae55 | 156 | if (BIO_get_init(b)) { |
0f113f3e MC |
157 | ppmd = ptr; |
158 | *ppmd = ctx->digest; | |
159 | } else | |
160 | ret = 0; | |
161 | break; | |
162 | case BIO_C_GET_MD_CTX: | |
163 | pctx = ptr; | |
164 | *pctx = ctx; | |
a146ae55 | 165 | BIO_set_init(b, 1); |
0f113f3e MC |
166 | break; |
167 | case BIO_C_SET_MD_CTX: | |
a146ae55 MC |
168 | if (BIO_get_init(b)) |
169 | BIO_set_data(b, ptr); | |
0f113f3e MC |
170 | else |
171 | ret = 0; | |
172 | break; | |
173 | case BIO_C_DO_STATE_MACHINE: | |
174 | BIO_clear_retry_flags(b); | |
a146ae55 | 175 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
176 | BIO_copy_next_retry(b); |
177 | break; | |
d02b48c6 | 178 | |
0f113f3e MC |
179 | case BIO_C_SET_MD: |
180 | md = ptr; | |
181 | ret = EVP_DigestInit_ex(ctx, md, NULL); | |
182 | if (ret > 0) | |
a146ae55 | 183 | BIO_set_init(b, 1); |
0f113f3e MC |
184 | break; |
185 | case BIO_CTRL_DUP: | |
186 | dbio = ptr; | |
a146ae55 | 187 | dctx = BIO_get_data(dbio); |
0f113f3e MC |
188 | if (!EVP_MD_CTX_copy_ex(dctx, ctx)) |
189 | return 0; | |
a146ae55 | 190 | BIO_set_init(b, 1); |
0f113f3e MC |
191 | break; |
192 | default: | |
a146ae55 | 193 | ret = BIO_ctrl(next, cmd, num, ptr); |
0f113f3e MC |
194 | break; |
195 | } | |
196 | return (ret); | |
197 | } | |
d02b48c6 | 198 | |
13083215 | 199 | static long md_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) |
0f113f3e MC |
200 | { |
201 | long ret = 1; | |
a146ae55 MC |
202 | BIO *next; |
203 | ||
204 | next = BIO_next(b); | |
205 | ||
206 | if (next == NULL) | |
207 | return 0; | |
d3442bc7 | 208 | |
0f113f3e MC |
209 | switch (cmd) { |
210 | default: | |
a146ae55 | 211 | ret = BIO_callback_ctrl(next, cmd, fp); |
0f113f3e MC |
212 | break; |
213 | } | |
214 | return (ret); | |
215 | } | |
d3442bc7 | 216 | |
6b691a5c | 217 | static int md_gets(BIO *bp, char *buf, int size) |
0f113f3e MC |
218 | { |
219 | EVP_MD_CTX *ctx; | |
220 | unsigned int ret; | |
d02b48c6 | 221 | |
a146ae55 MC |
222 | ctx = BIO_get_data(bp); |
223 | ||
0f113f3e | 224 | if (size < ctx->digest->md_size) |
a146ae55 MC |
225 | return 0; |
226 | ||
0f113f3e MC |
227 | if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0) |
228 | return -1; | |
d02b48c6 | 229 | |
0f113f3e MC |
230 | return ((int)ret); |
231 | } |