Fun 0.41.5
The programming language that makes You have fun
Loading...
Searching...
No Matches
openssl.c
Go to the documentation of this file.
1/*
2 * This file is part of the Fun programming language.
3 * https://fun-lang.xyz/
4 *
5 * Copyright 2026 Johannes Findeisen <you@hanez.org>
6 * Licensed under the terms of the Apache-2.0 license.
7 * https://opensource.org/license/apache-2-0
8 */
9
19
20/*
21 * OpenSSL integration helpers (MD5, RIPEMD-160, SHA-256, SHA-512)
22 */
23
24#ifdef FUN_WITH_OPENSSL
25#include <openssl/evp.h>
26/* Always use EVP_MD_get_size; if headers don't declare it, provide a
27 * forward declaration to allow linking against OpenSSL libcrypto. */
28#ifndef EVP_MD_get_size
29int EVP_MD_get_size(const EVP_MD *md);
30#endif
31#endif
32#include <stdlib.h>
33
44static char *fun_openssl_md5_hex(const unsigned char *data, size_t len) {
45 static const char hexdig[] = "0123456789abcdef";
46 if (!data && len != 0) return NULL;
47#ifdef FUN_WITH_OPENSSL
48 const EVP_MD *md = EVP_md5();
49 if (!md) return NULL;
50 int dlen = EVP_MD_get_size(md);
51 if (dlen <= 0) return NULL;
52 unsigned char *digest = (unsigned char *)malloc((size_t)dlen);
53 if (!digest) return NULL;
54 unsigned int out_len = 0;
55 int ok;
56 if (len == 0) {
57 // EVP_Digest handles zero-length fine as well
58 ok = EVP_Digest(NULL, 0, digest, &out_len, md, NULL);
59 } else {
60 ok = EVP_Digest(data, len, digest, &out_len, md, NULL);
61 }
62 if (ok != 1 || (int)out_len != dlen) {
63 free(digest);
64 return NULL;
65 }
66 char *hex = (char *)malloc((size_t)dlen * 2 + 1);
67 if (!hex) {
68 free(digest);
69 return NULL;
70 }
71 for (int i = 0; i < dlen; ++i) {
72 hex[2 * i] = hexdig[(digest[i] >> 4) & 0xF];
73 hex[2 * i + 1] = hexdig[digest[i] & 0xF];
74 }
75 hex[dlen * 2] = '\0';
76 free(digest);
77 return hex;
78#else
79 char *hex = (char *)malloc(1);
80 if (hex) hex[0] = '\0';
81 return hex;
82#endif
83}
84
94static char *fun_openssl_sha256_hex(const unsigned char *data, size_t len) {
95 static const char hexdig[] = "0123456789abcdef";
96 if (!data && len != 0) return NULL;
97#ifdef FUN_WITH_OPENSSL
98 const EVP_MD *md = EVP_sha256();
99 if (!md) return NULL;
100 int dlen = EVP_MD_get_size(md);
101 if (dlen <= 0) return NULL;
102 unsigned char *digest = (unsigned char *)malloc((size_t)dlen);
103 if (!digest) return NULL;
104 unsigned int out_len = 0;
105 int ok;
106 if (len == 0) {
107 ok = EVP_Digest(NULL, 0, digest, &out_len, md, NULL);
108 } else {
109 ok = EVP_Digest(data, len, digest, &out_len, md, NULL);
110 }
111 if (ok != 1 || (int)out_len != dlen) {
112 free(digest);
113 return NULL;
114 }
115 char *hex = (char *)malloc((size_t)dlen * 2 + 1);
116 if (!hex) {
117 free(digest);
118 return NULL;
119 }
120 for (int i = 0; i < dlen; ++i) {
121 hex[2 * i] = hexdig[(digest[i] >> 4) & 0xF];
122 hex[2 * i + 1] = hexdig[digest[i] & 0xF];
123 }
124 hex[dlen * 2] = '\0';
125 free(digest);
126 return hex;
127#else
128 char *hex = (char *)malloc(1);
129 if (hex) hex[0] = '\0';
130 return hex;
131#endif
132}
133
143static char *fun_openssl_sha512_hex(const unsigned char *data, size_t len) {
144 static const char hexdig[] = "0123456789abcdef";
145 if (!data && len != 0) return NULL;
146#ifdef FUN_WITH_OPENSSL
147 const EVP_MD *md = EVP_sha512();
148 if (!md) return NULL;
149 int dlen = EVP_MD_get_size(md);
150 if (dlen <= 0) return NULL;
151 unsigned char *digest = (unsigned char *)malloc((size_t)dlen);
152 if (!digest) return NULL;
153 unsigned int out_len = 0;
154 int ok;
155 if (len == 0) {
156 ok = EVP_Digest(NULL, 0, digest, &out_len, md, NULL);
157 } else {
158 ok = EVP_Digest(data, len, digest, &out_len, md, NULL);
159 }
160 if (ok != 1 || (int)out_len != dlen) {
161 free(digest);
162 return NULL;
163 }
164 char *hex = (char *)malloc((size_t)dlen * 2 + 1);
165 if (!hex) {
166 free(digest);
167 return NULL;
168 }
169 for (int i = 0; i < dlen; ++i) {
170 hex[2 * i] = hexdig[(digest[i] >> 4) & 0xF];
171 hex[2 * i + 1] = hexdig[digest[i] & 0xF];
172 }
173 hex[dlen * 2] = '\0';
174 free(digest);
175 return hex;
176#else
177 char *hex = (char *)malloc(1);
178 if (hex) hex[0] = '\0';
179 return hex;
180#endif
181}
182
196static char *fun_openssl_ripemd160_hex(const unsigned char *data, size_t len) {
197 static const char hexdig[] = "0123456789abcdef";
198 if (!data && len != 0) return NULL;
199#ifdef FUN_WITH_OPENSSL
200 const EVP_MD *md = EVP_ripemd160();
201 if (!md) return NULL;
202 int dlen = EVP_MD_get_size(md);
203 if (dlen <= 0) return NULL;
204 unsigned char *digest = (unsigned char *)malloc((size_t)dlen);
205 if (!digest) return NULL;
206 unsigned int out_len = 0;
207 int ok;
208 if (len == 0) {
209 ok = EVP_Digest(NULL, 0, digest, &out_len, md, NULL);
210 } else {
211 ok = EVP_Digest(data, len, digest, &out_len, md, NULL);
212 }
213 if (ok != 1 || (int)out_len != dlen) {
214 free(digest);
215 return NULL;
216 }
217 char *hex = (char *)malloc((size_t)dlen * 2 + 1);
218 if (!hex) {
219 free(digest);
220 return NULL;
221 }
222 for (int i = 0; i < dlen; ++i) {
223 hex[2 * i] = hexdig[(digest[i] >> 4) & 0xF];
224 hex[2 * i + 1] = hexdig[digest[i] & 0xF];
225 }
226 hex[dlen * 2] = '\0';
227 free(digest);
228 return hex;
229#else
230 char *hex = (char *)malloc(1);
231 if (hex) hex[0] = '\0';
232 return hex;
233#endif
234}
int ok
Definition contains.c:38
size_t len
Definition input_line.c:102
free(vals)
char * hex
Definition md5.c:39