1/*
2 * $Id: openssl_missing.c 32230 2011-06-26 01:32:03Z emboss $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
5 * All rights reserved.
6 */
7/*
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
10 */
11#include RUBY_EXTCONF_H
12
13#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ST_ENGINE)
14# include <openssl/engine.h>
15#endif
16#include <openssl/x509_vfy.h>
17
18#if !defined(OPENSSL_NO_HMAC)
19#include <string.h> /* memcpy() */
20#include <openssl/hmac.h>
21
22#include "openssl_missing.h"
23
24#if !defined(HAVE_HMAC_CTX_COPY)
25void
26HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
27{
28    if (!out || !in) return;
29    memcpy(out, in, sizeof(HMAC_CTX));
30
31    EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
32    EVP_MD_CTX_copy(&out->i_ctx, &in->i_ctx);
33    EVP_MD_CTX_copy(&out->o_ctx, &in->o_ctx);
34}
35#endif /* HAVE_HMAC_CTX_COPY */
36#endif /* NO_HMAC */
37
38#if !defined(HAVE_X509_STORE_SET_EX_DATA)
39int X509_STORE_set_ex_data(X509_STORE *str, int idx, void *data)
40{
41    return CRYPTO_set_ex_data(&str->ex_data, idx, data);
42}
43#endif
44
45#if !defined(HAVE_X509_STORE_GET_EX_DATA)
46void *X509_STORE_get_ex_data(X509_STORE *str, int idx)
47{
48    return CRYPTO_get_ex_data(&str->ex_data, idx);
49}
50#endif
51
52#if !defined(HAVE_EVP_MD_CTX_CREATE)
53EVP_MD_CTX *
54EVP_MD_CTX_create(void)
55{
56    EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
57    if (!ctx) return NULL;
58
59    memset(ctx, 0, sizeof(EVP_MD_CTX));
60
61    return ctx;
62}
63#endif
64
65#if !defined(HAVE_EVP_MD_CTX_CLEANUP)
66int
67EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
68{
69    /* FIXME!!! */
70    memset(ctx, 0, sizeof(EVP_MD_CTX));
71
72    return 1;
73}
74#endif
75
76#if !defined(HAVE_EVP_MD_CTX_DESTROY)
77void
78EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
79{
80    EVP_MD_CTX_cleanup(ctx);
81    OPENSSL_free(ctx);
82}
83#endif
84
85#if !defined(HAVE_EVP_MD_CTX_INIT)
86void
87EVP_MD_CTX_init(EVP_MD_CTX *ctx)
88{
89    memset(ctx, 0, sizeof(EVP_MD_CTX));
90}
91#endif
92
93#if !defined(HAVE_HMAC_CTX_INIT)
94void
95HMAC_CTX_init(HMAC_CTX *ctx)
96{
97    EVP_MD_CTX_init(&ctx->i_ctx);
98    EVP_MD_CTX_init(&ctx->o_ctx);
99    EVP_MD_CTX_init(&ctx->md_ctx);
100}
101#endif
102
103#if !defined(HAVE_HMAC_CTX_CLEANUP)
104void
105HMAC_CTX_cleanup(HMAC_CTX *ctx)
106{
107    EVP_MD_CTX_cleanup(&ctx->i_ctx);
108    EVP_MD_CTX_cleanup(&ctx->o_ctx);
109    EVP_MD_CTX_cleanup(&ctx->md_ctx);
110    memset(ctx, 0, sizeof(HMAC_CTX));
111}
112#endif
113
114#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
115/*
116 * this function does not exist in OpenSSL yet... or ever?.
117 * a future version may break this function.
118 * tested on 0.9.7d.
119 */
120int
121EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, EVP_CIPHER_CTX *in)
122{
123    memcpy(out, in, sizeof(EVP_CIPHER_CTX));
124
125#if defined(HAVE_ENGINE_ADD) && defined(HAVE_ST_ENGINE)
126    if (in->engine) ENGINE_add(out->engine);
127    if (in->cipher_data) {
128	out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
129	memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
130    }
131#endif
132
133    return 1;
134}
135#endif
136
137#if !defined(HAVE_X509_CRL_SET_VERSION)
138int
139X509_CRL_set_version(X509_CRL *x, long version)
140{
141    if (x == NULL || x->crl == NULL) return 0;
142    if (x->crl->version == NULL) {
143	x->crl->version = M_ASN1_INTEGER_new();
144	if (x->crl->version == NULL) return 0;
145    }
146    return ASN1_INTEGER_set(x->crl->version, version);
147}
148#endif
149
150#if !defined(HAVE_X509_CRL_SET_ISSUER_NAME)
151int
152X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
153{
154    if (x == NULL || x->crl == NULL) return 0;
155    return X509_NAME_set(&x->crl->issuer, name);
156}
157#endif
158
159#if !defined(HAVE_X509_CRL_SORT)
160int
161X509_CRL_sort(X509_CRL *c)
162{
163    int i;
164    X509_REVOKED *r;
165    /* sort the data so it will be written in serial
166     * number order */
167    sk_X509_REVOKED_sort(c->crl->revoked);
168    for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++) {
169	r=sk_X509_REVOKED_value(c->crl->revoked, i);
170	r->sequence=i;
171    }
172    return 1;
173}
174#endif
175
176#if !defined(HAVE_X509_CRL_ADD0_REVOKED)
177static int
178OSSL_X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
179{
180    return(ASN1_STRING_cmp(
181		(ASN1_STRING *)(*a)->serialNumber,
182		(ASN1_STRING *)(*b)->serialNumber));
183}
184
185int
186X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
187{
188    X509_CRL_INFO *inf;
189
190    inf = crl->crl;
191    if (!inf->revoked)
192	inf->revoked = sk_X509_REVOKED_new(OSSL_X509_REVOKED_cmp);
193    if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev))
194	return 0;
195    return 1;
196}
197#endif
198
199#if !defined(HAVE_BN_MOD_SQR)
200int
201BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
202{
203    if (!BN_sqr(r, (BIGNUM*)a, ctx)) return 0;
204    return BN_mod(r, r, m, ctx);
205}
206#endif
207
208#if !defined(HAVE_BN_MOD_ADD) || !defined(HAVE_BN_MOD_SUB)
209int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
210{
211    if (!BN_mod(r,m,d,ctx)) return 0;
212    if (!r->neg) return 1;
213    return (d->neg ? BN_sub : BN_add)(r, r, d);
214}
215#endif
216
217#if !defined(HAVE_BN_MOD_ADD)
218int
219BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
220{
221    if (!BN_add(r, a, b)) return 0;
222    return BN_nnmod(r, r, m, ctx);
223}
224#endif
225
226#if !defined(HAVE_BN_MOD_SUB)
227int
228BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
229{
230    if (!BN_sub(r, a, b)) return 0;
231    return BN_nnmod(r, r, m, ctx);
232}
233#endif
234
235#if !defined(HAVE_BN_RAND_RANGE) || !defined(HAVE_BN_PSEUDO_RAND_RANGE)
236static int
237bn_rand_range(int pseudo, BIGNUM *r, BIGNUM *range)
238{
239    int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
240    int n;
241
242    if (range->neg || BN_is_zero(range)) return 0;
243
244    n = BN_num_bits(range);
245
246    if (n == 1) {
247	if (!BN_zero(r)) return 0;
248    } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
249	do {
250	    if (!bn_rand(r, n + 1, -1, 0)) return 0;
251	    if (BN_cmp(r ,range) >= 0) {
252		if (!BN_sub(r, r, range)) return 0;
253		if (BN_cmp(r, range) >= 0)
254		    if (!BN_sub(r, r, range)) return 0;
255	    }
256	} while (BN_cmp(r, range) >= 0);
257    } else {
258	do {
259	    if (!bn_rand(r, n, -1, 0)) return 0;
260	} while (BN_cmp(r, range) >= 0);
261    }
262
263    return 1;
264}
265#endif
266
267#if !defined(HAVE_BN_RAND_RANGE)
268int
269BN_rand_range(BIGNUM *r, BIGNUM *range)
270{
271    return bn_rand_range(0, r, range);
272}
273#endif
274
275#if !defined(HAVE_BN_PSEUDO_RAND_RANGE)
276int
277BN_pseudo_rand_range(BIGNUM *r, BIGNUM *range)
278{
279    return bn_rand_range(1, r, range);
280}
281#endif
282
283#if !defined(HAVE_CONF_GET1_DEFAULT_CONFIG_FILE)
284#define OPENSSL_CONF "openssl.cnf"
285char *
286CONF_get1_default_config_file(void)
287{
288    char *file;
289    int len;
290
291    file = getenv("OPENSSL_CONF");
292    if (file) return BUF_strdup(file);
293    len = strlen(X509_get_default_cert_area());
294#ifndef OPENSSL_SYS_VMS
295    len++;
296#endif
297    len += strlen(OPENSSL_CONF);
298    file = OPENSSL_malloc(len + 1);
299    if (!file) return NULL;
300    strcpy(file,X509_get_default_cert_area());
301#ifndef OPENSSL_SYS_VMS
302    strcat(file,"/");
303#endif
304    strcat(file,OPENSSL_CONF);
305
306    return file;
307}
308#endif
309
310#if !defined(HAVE_PEM_DEF_CALLBACK)
311#define OSSL_PASS_MIN_LENGTH 4
312int
313PEM_def_callback(char *buf, int num, int w, void *key)
314{
315    int i,j;
316    const char *prompt;
317
318    if (key) {
319	i = strlen(key);
320	i = (i > num) ? num : i;
321	memcpy(buf, key, i);
322	return i;
323    }
324
325    prompt = EVP_get_pw_prompt();
326    if (prompt == NULL) prompt = "Enter PEM pass phrase:";
327    for (;;) {
328	i = EVP_read_pw_string(buf, num, prompt, w);
329	if (i != 0) {
330	    memset(buf, 0, (unsigned int)num);
331	    return(-1);
332	}
333	j = strlen(buf);
334	if (j < OSSL_PASS_MIN_LENGTH) {
335	    fprintf(stderr,
336		    "phrase is too short, needs to be at least %d chars\n",
337		    OSSL_PASS_MIN_LENGTH);
338	}
339	else break;
340    }
341    return j;
342}
343#endif
344
345#if !defined(HAVE_ASN1_PUT_EOC)
346int
347ASN1_put_eoc(unsigned char **pp)
348{
349    unsigned char *p = *pp;
350    *p++ = 0;
351    *p++ = 0;
352    *pp = p;
353    return 2;
354}
355#endif
356
357