~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to src/openvpn/cryptoapi.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2004 Peter 'Luna' Runestig <peter@runestig.com>
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without modifi-
 
6
 * cation, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *   o  Redistributions of source code must retain the above copyright notice,
 
9
 *      this list of conditions and the following disclaimer.
 
10
 *
 
11
 *   o  Redistributions in binary form must reproduce the above copyright no-
 
12
 *      tice, this list of conditions and the following disclaimer in the do-
 
13
 *      cumentation and/or other materials provided with the distribution.
 
14
 *
 
15
 *   o  The names of the contributors may not be used to endorse or promote
 
16
 *      products derived from this software without specific prior written
 
17
 *      permission.
 
18
 *
 
19
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
20
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 
21
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
22
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
 
23
 * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
 
24
 * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
 
26
 * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
 
27
 * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 
28
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#include "config.h"
 
33
#elif defined(_MSC_VER)
 
34
#include "config-msvc.h"
 
35
#endif
 
36
 
 
37
#include "syshead.h"
 
38
 
 
39
#ifdef ENABLE_CRYPTOAPI
 
40
 
 
41
#include <openssl/ssl.h>
 
42
#include <openssl/err.h>
 
43
#include <windows.h>
 
44
#include <wincrypt.h>
 
45
#include <stdio.h>
 
46
#include <ctype.h>
 
47
#include <assert.h>
 
48
 
 
49
/* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while
 
50
 * MinGW32-w64 defines all macros used. This is a hack around that problem.
 
51
 */
 
52
#ifndef CERT_SYSTEM_STORE_LOCATION_SHIFT
 
53
#define CERT_SYSTEM_STORE_LOCATION_SHIFT 16
 
54
#endif
 
55
#ifndef CERT_SYSTEM_STORE_CURRENT_USER_ID
 
56
#define CERT_SYSTEM_STORE_CURRENT_USER_ID 1
 
57
#endif
 
58
#ifndef CERT_SYSTEM_STORE_CURRENT_USER
 
59
#define CERT_SYSTEM_STORE_CURRENT_USER (CERT_SYSTEM_STORE_CURRENT_USER_ID << CERT_SYSTEM_STORE_LOCATION_SHIFT)
 
60
#endif
 
61
#ifndef CERT_STORE_READONLY_FLAG
 
62
#define CERT_STORE_READONLY_FLAG 0x00008000
 
63
#endif
 
64
#ifndef CERT_STORE_OPEN_EXISTING_FLAG
 
65
#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
 
66
#endif
 
67
 
 
68
/* Size of an SSL signature: MD5+SHA1 */
 
69
#define SSL_SIG_LENGTH  36
 
70
 
 
71
/* try to funnel any Windows/CryptoAPI error messages to OpenSSL ERR_... */
 
72
#define ERR_LIB_CRYPTOAPI (ERR_LIB_USER + 69)   /* 69 is just a number... */
 
73
#define CRYPTOAPIerr(f)   err_put_ms_error(GetLastError(), (f), __FILE__, __LINE__)
 
74
#define CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE                  100
 
75
#define CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE          101
 
76
#define CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY   102
 
77
#define CRYPTOAPI_F_CRYPT_CREATE_HASH                       103
 
78
#define CRYPTOAPI_F_CRYPT_GET_HASH_PARAM                    104
 
79
#define CRYPTOAPI_F_CRYPT_SET_HASH_PARAM                    105
 
80
#define CRYPTOAPI_F_CRYPT_SIGN_HASH                         106
 
81
#define CRYPTOAPI_F_LOAD_LIBRARY                            107
 
82
#define CRYPTOAPI_F_GET_PROC_ADDRESS                        108
 
83
 
 
84
static ERR_STRING_DATA CRYPTOAPI_str_functs[] = {
 
85
    { ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0),                                    "microsoft cryptoapi"},
 
86
    { ERR_PACK(0, CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE, 0),                   "CertOpenSystemStore" },
 
87
    { ERR_PACK(0, CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE, 0),           "CertFindCertificateInStore" },
 
88
    { ERR_PACK(0, CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY, 0),    "CryptAcquireCertificatePrivateKey" },
 
89
    { ERR_PACK(0, CRYPTOAPI_F_CRYPT_CREATE_HASH, 0),                        "CryptCreateHash" },
 
90
    { ERR_PACK(0, CRYPTOAPI_F_CRYPT_GET_HASH_PARAM, 0),                     "CryptGetHashParam" },
 
91
    { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SET_HASH_PARAM, 0),                     "CryptSetHashParam" },
 
92
    { ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0),                          "CryptSignHash" },
 
93
    { ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0),                             "LoadLibrary" },
 
94
    { ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0),                         "GetProcAddress" },
 
95
    { 0, NULL }
 
96
};
 
97
 
 
98
typedef struct _CAPI_DATA {
 
99
    const CERT_CONTEXT *cert_context;
 
100
    HCRYPTPROV crypt_prov;
 
101
    DWORD key_spec;
 
102
    BOOL free_crypt_prov;
 
103
} CAPI_DATA;
 
104
 
 
105
static char *ms_error_text(DWORD ms_err)
 
106
{
 
107
    LPVOID lpMsgBuf = NULL;
 
108
    char *rv = NULL;
 
109
 
 
110
    FormatMessage(
 
111
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
 
112
        FORMAT_MESSAGE_FROM_SYSTEM |
 
113
        FORMAT_MESSAGE_IGNORE_INSERTS,
 
114
        NULL, ms_err,
 
115
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
 
116
        (LPTSTR) &lpMsgBuf, 0, NULL);
 
117
    if (lpMsgBuf) {
 
118
        char *p;
 
119
        rv = strdup(lpMsgBuf);
 
120
        LocalFree(lpMsgBuf);
 
121
        /* trim to the left */
 
122
        if (rv)
 
123
            for (p = rv + strlen(rv) - 1; p >= rv; p--) {
 
124
                if (isspace(*p))
 
125
                    *p = '\0';
 
126
                else
 
127
                    break;
 
128
            }
 
129
    }
 
130
    return rv;
 
131
}
 
132
 
 
133
static void err_put_ms_error(DWORD ms_err, int func, const char *file, int line)
 
134
{
 
135
    static int init = 0;
 
136
#   define ERR_MAP_SZ 16
 
137
    static struct {
 
138
        int err;
 
139
        DWORD ms_err;       /* I don't think we get more than 16 *different* errors */
 
140
    } err_map[ERR_MAP_SZ];  /* in here, before we give up the whole thing...        */
 
141
    int i;
 
142
 
 
143
    if (ms_err == 0)
 
144
        /* 0 is not an error */
 
145
        return;
 
146
    if (!init) {
 
147
        ERR_load_strings(ERR_LIB_CRYPTOAPI, CRYPTOAPI_str_functs);
 
148
        memset(&err_map, 0, sizeof(err_map));
 
149
        init++;
 
150
    }
 
151
    /* since MS error codes are 32 bit, and the ones in the ERR_... system is
 
152
     * only 12, we must have a mapping table between them.  */
 
153
    for (i = 0; i < ERR_MAP_SZ; i++) {
 
154
        if (err_map[i].ms_err == ms_err) {
 
155
            ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
 
156
            break;
 
157
        } else if (err_map[i].ms_err == 0 ) {
 
158
            /* end of table, add new entry */
 
159
            ERR_STRING_DATA *esd = calloc(2, sizeof(*esd));
 
160
            if (esd == NULL)
 
161
                break;
 
162
            err_map[i].ms_err = ms_err;
 
163
            err_map[i].err = esd->error = i + 100;
 
164
            esd->string = ms_error_text(ms_err);
 
165
            ERR_load_strings(ERR_LIB_CRYPTOAPI, esd);
 
166
            ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
 
167
            break;
 
168
        }
 
169
    }
 
170
}
 
171
 
 
172
/* encrypt */
 
173
static int rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 
174
{
 
175
    /* I haven't been able to trigger this one, but I want to know if it happens... */
 
176
    assert(0);
 
177
 
 
178
    return 0;
 
179
}
 
180
 
 
181
/* verify arbitrary data */
 
182
static int rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 
183
{
 
184
    /* I haven't been able to trigger this one, but I want to know if it happens... */
 
185
    assert(0);
 
186
 
 
187
    return 0;
 
188
}
 
189
 
 
190
/* sign arbitrary data */
 
191
static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 
192
{
 
193
    CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
 
194
    HCRYPTHASH hash;
 
195
    DWORD hash_size, len, i;
 
196
    unsigned char *buf;
 
197
 
 
198
    if (cd == NULL) {
 
199
        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
 
200
        return 0;
 
201
    }
 
202
    if (padding != RSA_PKCS1_PADDING) {
 
203
        /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */
 
204
        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
 
205
        return 0;
 
206
    }
 
207
    /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would
 
208
     * be way to straightforward for M$, I guess... So we have to do it this
 
209
     * tricky way instead, by creating a "Hash", and load the already-made hash
 
210
     * from 'from' into it.  */
 
211
    /* For now, we only support NID_md5_sha1 */
 
212
    if (flen != SSL_SIG_LENGTH) {
 
213
        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
 
214
        return 0;
 
215
    }
 
216
    if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) {
 
217
        CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_CREATE_HASH);
 
218
        return 0;
 
219
    }
 
220
    len = sizeof(hash_size);
 
221
    if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) {
 
222
        CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_GET_HASH_PARAM);
 
223
        CryptDestroyHash(hash);
 
224
        return 0;
 
225
    }
 
226
    if ((int) hash_size != flen) {
 
227
        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
 
228
        CryptDestroyHash(hash);
 
229
        return 0;
 
230
    }
 
231
    if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
 
232
        CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SET_HASH_PARAM);
 
233
        CryptDestroyHash(hash);
 
234
        return 0;
 
235
    }
 
236
 
 
237
    len = RSA_size(rsa);
 
238
    buf = malloc(len);
 
239
    if (buf == NULL) {
 
240
        RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
 
241
        CryptDestroyHash(hash);
 
242
        return 0;
 
243
    }
 
244
    if (!CryptSignHash(hash, cd->key_spec, NULL, 0, buf, &len)) {
 
245
        CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SIGN_HASH);
 
246
        CryptDestroyHash(hash);
 
247
        free(buf);
 
248
        return 0;
 
249
    }
 
250
    /* and now, we have to reverse the byte-order in the result from CryptSignHash()... */
 
251
    for (i = 0; i < len; i++)
 
252
        to[i] = buf[len - i - 1];
 
253
    free(buf);
 
254
 
 
255
    CryptDestroyHash(hash);
 
256
    return len;
 
257
}
 
258
 
 
259
/* decrypt */
 
260
static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 
261
{
 
262
    /* I haven't been able to trigger this one, but I want to know if it happens... */
 
263
    assert(0);
 
264
 
 
265
    return 0;
 
266
}
 
267
 
 
268
/* called at RSA_new */
 
269
static int init(RSA *rsa)
 
270
{
 
271
 
 
272
    return 0;
 
273
}
 
274
 
 
275
/* called at RSA_free */
 
276
static int finish(RSA *rsa)
 
277
{
 
278
    CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
 
279
 
 
280
    if (cd == NULL)
 
281
        return 0;
 
282
    if (cd->crypt_prov && cd->free_crypt_prov)
 
283
        CryptReleaseContext(cd->crypt_prov, 0);
 
284
    if (cd->cert_context)
 
285
        CertFreeCertificateContext(cd->cert_context);
 
286
    free(rsa->meth->app_data);
 
287
    free((char *) rsa->meth);
 
288
    rsa->meth = NULL;
 
289
    return 1;
 
290
}
 
291
 
 
292
static const CERT_CONTEXT *find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store)
 
293
{
 
294
    /* Find, and use, the desired certificate from the store. The
 
295
     * 'cert_prop' certificate search string can look like this:
 
296
     * SUBJ:<certificate substring to match>
 
297
     * THUMB:<certificate thumbprint hex value>, e.g.
 
298
     *     THUMB:f6 49 24 41 01 b4 fb 44 0c ce f4 36 ae d0 c4 c9 df 7a b6 28
 
299
     */
 
300
    const CERT_CONTEXT *rv = NULL;
 
301
 
 
302
    if (!strncmp(cert_prop, "SUBJ:", 5)) {
 
303
        /* skip the tag */
 
304
        cert_prop += 5;
 
305
        rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
 
306
                0, CERT_FIND_SUBJECT_STR_A, cert_prop, NULL);
 
307
 
 
308
    } else if (!strncmp(cert_prop, "THUMB:", 6)) {
 
309
        unsigned char hash[255];
 
310
        char *p;
 
311
        int i, x = 0;
 
312
        CRYPT_HASH_BLOB blob;
 
313
 
 
314
        /* skip the tag */
 
315
        cert_prop += 6;
 
316
        for (p = (char *) cert_prop, i = 0; *p && i < sizeof(hash); i++) {
 
317
            if (*p >= '0' && *p <= '9')
 
318
                x = (*p - '0') << 4;
 
319
            else if (*p >= 'A' && *p <= 'F')
 
320
                x = (*p - 'A' + 10) << 4;
 
321
            else if (*p >= 'a' && *p <= 'f')
 
322
                x = (*p - 'a' + 10) << 4;
 
323
            if (!*++p)  /* unexpected end of string */
 
324
                break;
 
325
            if (*p >= '0' && *p <= '9')
 
326
                x += *p - '0';
 
327
            else if (*p >= 'A' && *p <= 'F')
 
328
                x += *p - 'A' + 10;
 
329
            else if (*p >= 'a' && *p <= 'f')
 
330
                x += *p - 'a' + 10;
 
331
            hash[i] = x;
 
332
            /* skip any space(s) between hex numbers */
 
333
            for (p++; *p && *p == ' '; p++);
 
334
        }
 
335
        blob.cbData = i;
 
336
        blob.pbData = (unsigned char *) &hash;
 
337
        rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
 
338
                0, CERT_FIND_HASH, &blob, NULL);
 
339
 
 
340
    }
 
341
 
 
342
    return rv;
 
343
}
 
344
 
 
345
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
 
346
{
 
347
    HCERTSTORE cs;
 
348
    X509 *cert = NULL;
 
349
    RSA *rsa = NULL, *pub_rsa;
 
350
    CAPI_DATA *cd = calloc(1, sizeof(*cd));
 
351
    RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method));
 
352
 
 
353
    if (cd == NULL || my_rsa_method == NULL) {
 
354
        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
 
355
        goto err;
 
356
    }
 
357
    /* search CURRENT_USER first, then LOCAL_MACHINE */
 
358
    cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER |
 
359
                       CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
 
360
    if (cs == NULL) {
 
361
        CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
 
362
        goto err;
 
363
    }
 
364
    cd->cert_context = find_certificate_in_store(cert_prop, cs);
 
365
    CertCloseStore(cs, 0);
 
366
    if (!cd->cert_context) {
 
367
        cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE |
 
368
                           CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
 
369
        if (cs == NULL) {
 
370
            CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
 
371
            goto err;
 
372
        }
 
373
        cd->cert_context = find_certificate_in_store(cert_prop, cs);
 
374
        CertCloseStore(cs, 0);
 
375
        if (cd->cert_context == NULL) {
 
376
            CRYPTOAPIerr(CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE);
 
377
            goto err;
 
378
        }
 
379
    }
 
380
 
 
381
    /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
 
382
    cert = d2i_X509(NULL, (const unsigned char **) &cd->cert_context->pbCertEncoded,
 
383
                    cd->cert_context->cbCertEncoded);
 
384
    if (cert == NULL) {
 
385
        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
 
386
        goto err;
 
387
    }
 
388
 
 
389
    /* set up stuff to use the private key */
 
390
    if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
 
391
            NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) {
 
392
        /* if we don't have a smart card reader here, and we try to access a
 
393
         * smart card certificate, we get:
 
394
         * "Error 1223: The operation was canceled by the user." */
 
395
        CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY);
 
396
        goto err;
 
397
    }
 
398
    /* here we don't need to do CryptGetUserKey() or anything; all necessary key
 
399
     * info is in cd->cert_context, and then, in cd->crypt_prov.  */
 
400
 
 
401
    my_rsa_method->name = "Microsoft CryptoAPI RSA Method";
 
402
    my_rsa_method->rsa_pub_enc = rsa_pub_enc;
 
403
    my_rsa_method->rsa_pub_dec = rsa_pub_dec;
 
404
    my_rsa_method->rsa_priv_enc = rsa_priv_enc;
 
405
    my_rsa_method->rsa_priv_dec = rsa_priv_dec;
 
406
    /* my_rsa_method->init = init; */
 
407
    my_rsa_method->finish = finish;
 
408
    my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK;
 
409
    my_rsa_method->app_data = (char *) cd;
 
410
 
 
411
    rsa = RSA_new();
 
412
    if (rsa == NULL) {
 
413
        SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
 
414
        goto err;
 
415
    }
 
416
 
 
417
    /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
 
418
     * so we do it here then...  */
 
419
    if (!SSL_CTX_use_certificate(ssl_ctx, cert))
 
420
        goto err;
 
421
    /* the public key */
 
422
    pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
 
423
    /* SSL_CTX_use_certificate() increased the reference count in 'cert', so
 
424
     * we decrease it here with X509_free(), or it will never be cleaned up. */
 
425
    X509_free(cert);
 
426
    cert = NULL;
 
427
 
 
428
    /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */
 
429
    /* rsa->n indicates the key size */
 
430
    rsa->n = BN_dup(pub_rsa->n);
 
431
    rsa->flags |= RSA_FLAG_EXT_PKEY;
 
432
    if (!RSA_set_method(rsa, my_rsa_method))
 
433
        goto err;
 
434
 
 
435
    if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
 
436
        goto err;
 
437
    /* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so
 
438
     * we decrease it here with RSA_free(), or it will never be cleaned up. */
 
439
    RSA_free(rsa);
 
440
    return 1;
 
441
 
 
442
  err:
 
443
    if (cert)
 
444
        X509_free(cert);
 
445
    if (rsa)
 
446
        RSA_free(rsa);
 
447
    else {
 
448
        if (my_rsa_method)
 
449
            free(my_rsa_method);
 
450
        if (cd) {
 
451
            if (cd->free_crypt_prov && cd->crypt_prov)
 
452
                CryptReleaseContext(cd->crypt_prov, 0);
 
453
            if (cd->cert_context)
 
454
                CertFreeCertificateContext(cd->cert_context);
 
455
            free(cd);
 
456
        }
 
457
    }
 
458
    return 0;
 
459
}
 
460
 
 
461
#else
 
462
#ifdef _MSC_VER  /* Dummy function needed to avoid empty file compiler warning in Microsoft VC */
 
463
static void dummy (void) {}
 
464
#endif
 
465
#endif                          /* WIN32 */