Coverage Report

Created: 2018-08-29 13:53

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