/src/clamav/libclamav/conv.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved. |
3 | | * |
4 | | * Author: Shawn Webb |
5 | | * |
6 | | * This program is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU General Public License version 2 as |
8 | | * published by the Free Software Foundation. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
18 | | * MA 02110-1301, USA. |
19 | | */ |
20 | | |
21 | | #if HAVE_CONF_H |
22 | | #include "clamav-config.h" |
23 | | #endif |
24 | | |
25 | | #include <stdio.h> |
26 | | #include <stdlib.h> |
27 | | #include <string.h> |
28 | | |
29 | | #ifdef HAVE_UNISTD_H |
30 | | #include <unistd.h> |
31 | | #endif |
32 | | |
33 | | #include <math.h> |
34 | | |
35 | | #include <sys/types.h> |
36 | | |
37 | | #include <openssl/bio.h> |
38 | | #include <openssl/evp.h> |
39 | | |
40 | | // libclamav |
41 | | #include "clamav.h" |
42 | | #include "conv.h" |
43 | | |
44 | | /** Get the expected decoded length of a base64-encoded string |
45 | | * @param[in] data Base64-encoded string |
46 | | * @param[in] len length of the string |
47 | | * @return The expected decoded length of the base64-encoded string |
48 | | */ |
49 | | static size_t base64_len(const char *data, size_t len) |
50 | 0 | { |
51 | 0 | int padding = 0; |
52 | 0 | size_t i; |
53 | |
|
54 | 0 | if (!len) |
55 | 0 | return 0; |
56 | | |
57 | 0 | for (i = len - 1; i > 0 && data[i] == '='; i--) |
58 | 0 | padding++; |
59 | |
|
60 | 0 | return (size_t)((3 * len) / 4 - padding); |
61 | 0 | } |
62 | | |
63 | | /** Decode a base64-encoded string |
64 | | * @param[in] data The base64-encoded string |
65 | | * @param[in] len Length of the base64-encoded string |
66 | | * @param[out] obuf If obuf is not set to NULL, store the decoded data in obuf. Otherwise, the decoded data is stored in a dynamically-allocated buffer. |
67 | | * @param[out] olen The length of the decoded data |
68 | | * @return The base64-decoded data |
69 | | */ |
70 | | void *cl_base64_decode(char *data, size_t len, void *obuf, size_t *olen, int oneline) |
71 | 0 | { |
72 | 0 | BIO *bio, *b64; |
73 | 0 | void *buf; |
74 | |
|
75 | 0 | buf = (obuf) ? obuf : malloc(base64_len(data, len) + 1); |
76 | 0 | if (!(buf)) |
77 | 0 | return NULL; |
78 | | |
79 | 0 | b64 = BIO_new(BIO_f_base64()); |
80 | 0 | if (!(b64)) { |
81 | 0 | if (!(obuf)) |
82 | 0 | free(buf); |
83 | |
|
84 | 0 | return NULL; |
85 | 0 | } |
86 | | |
87 | 0 | bio = BIO_new_mem_buf(data, len); |
88 | 0 | if (!(bio)) { |
89 | 0 | BIO_free(b64); |
90 | 0 | if (!(obuf)) |
91 | 0 | free(buf); |
92 | |
|
93 | 0 | return NULL; |
94 | 0 | } |
95 | | |
96 | 0 | bio = BIO_push(b64, bio); |
97 | 0 | if (oneline) |
98 | 0 | BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); |
99 | |
|
100 | 0 | *olen = BIO_read(bio, buf, base64_len(data, len)); |
101 | |
|
102 | 0 | BIO_free_all(bio); |
103 | |
|
104 | 0 | return buf; |
105 | 0 | } |
106 | | |
107 | | /** Base64-encode data |
108 | | * @param[in] data The data to be encoded |
109 | | * @param[in] len The length of the data |
110 | | * @return A pointer to the base64-encoded data. The data is stored in a dynamically-allocated buffer. |
111 | | */ |
112 | | char *cl_base64_encode(void *data, size_t len) |
113 | 356k | { |
114 | 356k | BIO *bio, *b64; |
115 | 356k | char *buf, *p; |
116 | 356k | size_t elen; |
117 | | |
118 | 356k | b64 = BIO_new(BIO_f_base64()); |
119 | 356k | if (!(b64)) |
120 | 0 | return NULL; |
121 | 356k | bio = BIO_new(BIO_s_mem()); |
122 | 356k | if (!(bio)) { |
123 | 0 | BIO_free(b64); |
124 | 0 | return NULL; |
125 | 0 | } |
126 | | |
127 | 356k | bio = BIO_push(b64, bio); |
128 | 356k | BIO_write(bio, data, len); |
129 | | |
130 | 356k | BIO_flush(bio); |
131 | 356k | elen = (size_t)BIO_get_mem_data(bio, &buf); |
132 | | |
133 | | /* Ensure we're dealing with a NULL-terminated string */ |
134 | 356k | p = (char *)malloc(elen + 1); |
135 | 356k | if (NULL == p) { |
136 | 0 | BIO_free(b64); |
137 | 0 | return NULL; |
138 | 0 | } |
139 | 356k | memcpy((void *)p, (void *)buf, elen); |
140 | 356k | p[elen] = 0x00; |
141 | 356k | buf = p; |
142 | | |
143 | 356k | BIO_free_all(bio); |
144 | | |
145 | 356k | return buf; |
146 | 356k | } |
147 | | |
148 | | #if defined(CONV_SELF_TEST) |
149 | | |
150 | | int main(int argc, char *argv[]) |
151 | | { |
152 | | char *plaintext, *encoded, *decoded; |
153 | | unsigned char *sha_plaintext, *sha_decoded; |
154 | | size_t len; |
155 | | int ret = 0; |
156 | | unsigned int shalen; |
157 | | |
158 | | initialize_crypto(); |
159 | | |
160 | | plaintext = (argv[1]) ? argv[1] : "Hello. This is dog"; |
161 | | sha_plaintext = sha256(plaintext, strlen(plaintext), NULL, NULL); |
162 | | if (!(sha_plaintext)) { |
163 | | fprintf(stderr, "Could not generate sha256 of plaintext\n"); |
164 | | return 1; |
165 | | } |
166 | | |
167 | | encoded = base64_encode(plaintext, strlen(plaintext)); |
168 | | if (!(encoded)) { |
169 | | fprintf(stderr, "Could not base64 encode plaintest\n"); |
170 | | return 1; |
171 | | } |
172 | | fprintf(stderr, "Base64 encoded: %s\n", encoded); |
173 | | |
174 | | decoded = base64_decode(encoded, strlen(encoded), NULL, &len); |
175 | | if (!(decoded)) { |
176 | | fprintf(stderr, "Could not base64 decoded string\n"); |
177 | | return 1; |
178 | | } |
179 | | |
180 | | sha_decoded = sha256(decoded, len, NULL, &shalen); |
181 | | if (!(sha_decoded)) { |
182 | | fprintf(stderr, "Could not generate sha256 of decoded data\n"); |
183 | | return 1; |
184 | | } |
185 | | |
186 | | if (memcmp(sha_plaintext, sha_decoded, shalen)) { |
187 | | fprintf(stderr, "Decoded does not match plaintext: %s\n", decoded); |
188 | | ret = 1; |
189 | | } |
190 | | |
191 | | free(sha_decoded); |
192 | | free(sha_plaintext); |
193 | | free(encoded); |
194 | | free(decoded); |
195 | | |
196 | | cleanup_crypto(); |
197 | | |
198 | | return ret; |
199 | | } |
200 | | |
201 | | #endif |