~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/ssl/ssl_util_ssl.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/*                      _             _
 
18
 *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
 
19
 * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
 
20
 * | | | | | | (_) | (_| |   \__ \__ \ |
 
21
 * |_| |_| |_|\___/ \__,_|___|___/___/_|
 
22
 *                      |_____|
 
23
 *  ssl_util_ssl.c
 
24
 *  Additional Utility Functions for OpenSSL
 
25
 */
 
26
 
 
27
#include "ssl_private.h"
 
28
 
 
29
/*  _________________________________________________________________
 
30
**
 
31
**  Additional High-Level Functions for OpenSSL
 
32
**  _________________________________________________________________
 
33
*/
 
34
 
 
35
/* we initialize this index at startup time
 
36
 * and never write to it at request time,
 
37
 * so this static is thread safe.
 
38
 * also note that OpenSSL increments at static variable when
 
39
 * SSL_get_ex_new_index() is called, so we _must_ do this at startup.
 
40
 */
 
41
static int SSL_app_data2_idx = -1;
 
42
 
 
43
void SSL_init_app_data2_idx(void)
 
44
{
 
45
    int i;
 
46
 
 
47
    if (SSL_app_data2_idx > -1) {
 
48
        return;
 
49
    }
 
50
 
 
51
    /* we _do_ need to call this twice */
 
52
    for (i=0; i<=1; i++) {
 
53
        SSL_app_data2_idx =
 
54
            SSL_get_ex_new_index(0,
 
55
                                 "Second Application Data for SSL",
 
56
                                 NULL, NULL, NULL);
 
57
    }
 
58
}
 
59
 
 
60
void *SSL_get_app_data2(SSL *ssl)
 
61
{
 
62
    return (void *)SSL_get_ex_data(ssl, SSL_app_data2_idx);
 
63
}
 
64
 
 
65
void SSL_set_app_data2(SSL *ssl, void *arg)
 
66
{
 
67
    SSL_set_ex_data(ssl, SSL_app_data2_idx, (char *)arg);
 
68
    return;
 
69
}
 
70
 
 
71
/*  _________________________________________________________________
 
72
**
 
73
**  High-Level Certificate / Private Key Loading
 
74
**  _________________________________________________________________
 
75
*/
 
76
 
 
77
X509 *SSL_read_X509(char* filename, X509 **x509, modssl_read_bio_cb_fn *cb)
 
78
{
 
79
    X509 *rc;
 
80
    BIO *bioS;
 
81
    BIO *bioF;
 
82
 
 
83
    /* 1. try PEM (= DER+Base64+headers) */
 
84
    if ((bioS=BIO_new_file(filename, "r")) == NULL)
 
85
        return NULL;
 
86
    rc = modssl_PEM_read_bio_X509 (bioS, x509, cb, NULL);
 
87
    BIO_free(bioS);
 
88
 
 
89
    if (rc == NULL) {
 
90
        /* 2. try DER+Base64 */
 
91
        if ((bioS=BIO_new_file(filename, "r")) == NULL)
 
92
            return NULL;
 
93
 
 
94
        if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
 
95
            BIO_free(bioS);
 
96
            return NULL;
 
97
        }
 
98
        bioS = BIO_push(bioF, bioS);
 
99
        rc = d2i_X509_bio(bioS, NULL);
 
100
        BIO_free_all(bioS);
 
101
 
 
102
        if (rc == NULL) {
 
103
            /* 3. try plain DER */
 
104
            if ((bioS=BIO_new_file(filename, "r")) == NULL)
 
105
                return NULL;
 
106
            rc = d2i_X509_bio(bioS, NULL);
 
107
            BIO_free(bioS);
 
108
        }
 
109
    }
 
110
    if (rc != NULL && x509 != NULL) {
 
111
        if (*x509 != NULL)
 
112
            X509_free(*x509);
 
113
        *x509 = rc;
 
114
    }
 
115
    return rc;
 
116
}
 
117
 
 
118
#if SSL_LIBRARY_VERSION <= 0x00904100
 
119
static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key)
 
120
{
 
121
     return ((EVP_PKEY *)ASN1_d2i_bio(
 
122
             (char *(*)())EVP_PKEY_new,
 
123
             (char *(*)())d2i_PrivateKey,
 
124
             (bio), (unsigned char **)(key)));
 
125
}
 
126
#endif
 
127
 
 
128
EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, modssl_read_bio_cb_fn *cb, void *s)
 
129
{
 
130
    EVP_PKEY *rc;
 
131
    BIO *bioS;
 
132
    BIO *bioF;
 
133
 
 
134
    /* 1. try PEM (= DER+Base64+headers) */
 
135
    if ((bioS=BIO_new_file(filename, "r")) == NULL)
 
136
        return NULL;
 
137
    rc = modssl_PEM_read_bio_PrivateKey(bioS, key, cb, s);
 
138
    BIO_free(bioS);
 
139
 
 
140
    if (rc == NULL) {
 
141
        /* 2. try DER+Base64 */
 
142
        if ((bioS = BIO_new_file(filename, "r")) == NULL)
 
143
            return NULL;
 
144
 
 
145
        if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
 
146
            BIO_free(bioS);
 
147
            return NULL;
 
148
        }
 
149
        bioS = BIO_push(bioF, bioS);
 
150
        rc = d2i_PrivateKey_bio(bioS, NULL);
 
151
        BIO_free_all(bioS);
 
152
 
 
153
        if (rc == NULL) {
 
154
            /* 3. try plain DER */
 
155
            if ((bioS = BIO_new_file(filename, "r")) == NULL)
 
156
                return NULL;
 
157
            rc = d2i_PrivateKey_bio(bioS, NULL);
 
158
            BIO_free(bioS);
 
159
        }
 
160
    }
 
161
    if (rc != NULL && key != NULL) {
 
162
        if (*key != NULL)
 
163
            EVP_PKEY_free(*key);
 
164
        *key = rc;
 
165
    }
 
166
    return rc;
 
167
}
 
168
 
 
169
/*  _________________________________________________________________
 
170
**
 
171
**  Smart shutdown
 
172
**  _________________________________________________________________
 
173
*/
 
174
 
 
175
int SSL_smart_shutdown(SSL *ssl)
 
176
{
 
177
    int i;
 
178
    int rc;
 
179
 
 
180
    /*
 
181
     * Repeat the calls, because SSL_shutdown internally dispatches through a
 
182
     * little state machine. Usually only one or two interation should be
 
183
     * needed, so we restrict the total number of restrictions in order to
 
184
     * avoid process hangs in case the client played bad with the socket
 
185
     * connection and OpenSSL cannot recognize it.
 
186
     */
 
187
    rc = 0;
 
188
    for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) {
 
189
        if ((rc = SSL_shutdown(ssl)))
 
190
            break;
 
191
    }
 
192
    return rc;
 
193
}
 
194
 
 
195
/*  _________________________________________________________________
 
196
**
 
197
**  Certificate Revocation List (CRL) Storage
 
198
**  _________________________________________________________________
 
199
*/
 
200
 
 
201
X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
 
202
{
 
203
    X509_STORE *pStore;
 
204
    X509_LOOKUP *pLookup;
 
205
    int rv = 1;
 
206
 
 
207
    ERR_clear_error();
 
208
 
 
209
    if (cpFile == NULL && cpPath == NULL)
 
210
        return NULL;
 
211
    if ((pStore = X509_STORE_new()) == NULL)
 
212
        return NULL;
 
213
    if (cpFile != NULL) {
 
214
        pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file());
 
215
        if (pLookup == NULL) {
 
216
            X509_STORE_free(pStore);
 
217
            return NULL;
 
218
        }
 
219
        rv = X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
 
220
    }
 
221
    if (cpPath != NULL && rv == 1) {
 
222
        pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir());
 
223
        if (pLookup == NULL) {
 
224
            X509_STORE_free(pStore);
 
225
            return NULL;
 
226
        }
 
227
        rv = X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
 
228
    }
 
229
    return rv == 1 ? pStore : NULL;
 
230
}
 
231
 
 
232
int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
 
233
                          X509_NAME *pName, X509_OBJECT *pObj)
 
234
{
 
235
    X509_STORE_CTX pStoreCtx;
 
236
    int rc;
 
237
 
 
238
    X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
 
239
    rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
 
240
    X509_STORE_CTX_cleanup(&pStoreCtx);
 
241
    return rc;
 
242
}
 
243
 
 
244
/*  _________________________________________________________________
 
245
**
 
246
**  Cipher Suite Spec String Creation
 
247
**  _________________________________________________________________
 
248
*/
 
249
 
 
250
char *SSL_make_ciphersuite(apr_pool_t *p, SSL *ssl)
 
251
{
 
252
    STACK_OF(SSL_CIPHER) *sk;
 
253
    SSL_CIPHER *c;
 
254
    int i;
 
255
    int l;
 
256
    char *cpCipherSuite;
 
257
    char *cp;
 
258
 
 
259
    if (ssl == NULL)
 
260
        return "";
 
261
    if ((sk = (STACK_OF(SSL_CIPHER) *)SSL_get_ciphers(ssl)) == NULL)
 
262
        return "";
 
263
    l = 0;
 
264
    for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
 
265
        c = sk_SSL_CIPHER_value(sk, i);
 
266
        l += strlen(SSL_CIPHER_get_name(c))+2+1;
 
267
    }
 
268
    if (l == 0)
 
269
        return "";
 
270
    cpCipherSuite = (char *)apr_palloc(p, l+1);
 
271
    cp = cpCipherSuite;
 
272
    for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
 
273
        c = sk_SSL_CIPHER_value(sk, i);
 
274
        l = strlen(SSL_CIPHER_get_name(c));
 
275
        memcpy(cp, SSL_CIPHER_get_name(c), l);
 
276
        cp += l;
 
277
        *cp++ = '/';
 
278
        *cp++ = (SSL_CIPHER_get_valid(c) == 1 ? '1' : '0');
 
279
        *cp++ = ':';
 
280
    }
 
281
    *(cp-1) = NUL;
 
282
    return cpCipherSuite;
 
283
}
 
284
 
 
285
/*  _________________________________________________________________
 
286
**
 
287
**  Certificate Checks
 
288
**  _________________________________________________________________
 
289
*/
 
290
 
 
291
/* check whether cert contains extended key usage with a SGC tag */
 
292
BOOL SSL_X509_isSGC(X509 *cert)
 
293
{
 
294
#ifdef HAVE_SSL_X509V3_EXT_d2i
 
295
    X509_EXTENSION *ext;
 
296
    int ext_nid;
 
297
    STACK *sk;
 
298
    BOOL is_sgc;
 
299
    int idx;
 
300
    int i;
 
301
 
 
302
    is_sgc = FALSE;
 
303
    idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
 
304
    if (idx >= 0) {
 
305
        ext = X509_get_ext(cert, idx);
 
306
        if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
 
307
            for (i = 0; i < sk_num(sk); i++) {
 
308
                ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
 
309
                if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {
 
310
                    is_sgc = TRUE;
 
311
                    break;
 
312
                }
 
313
            }
 
314
        }
 
315
    }
 
316
    return is_sgc;
 
317
#else
 
318
    return FALSE;
 
319
#endif
 
320
}
 
321
 
 
322
/* retrieve basic constraints ingredients */
 
323
BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
 
324
{
 
325
#ifdef HAVE_SSL_X509V3_EXT_d2i
 
326
    X509_EXTENSION *ext;
 
327
    BASIC_CONSTRAINTS *bc;
 
328
    int idx;
 
329
    BIGNUM *bn = NULL;
 
330
    char *cp;
 
331
 
 
332
    if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0)
 
333
        return FALSE;
 
334
    ext = X509_get_ext(cert, idx);
 
335
    if (ext == NULL)
 
336
        return FALSE;
 
337
    if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL)
 
338
        return FALSE;
 
339
    *ca = bc->ca;
 
340
    *pathlen = -1 /* unlimited */;
 
341
    if (bc->pathlen != NULL) {
 
342
        if ((bn = ASN1_INTEGER_to_BN(bc->pathlen, NULL)) == NULL)
 
343
            return FALSE;
 
344
        if ((cp = BN_bn2dec(bn)) == NULL)
 
345
            return FALSE;
 
346
        *pathlen = atoi(cp);
 
347
        free(cp);
 
348
        BN_free(bn);
 
349
    }
 
350
    BASIC_CONSTRAINTS_free(bc);
 
351
    return TRUE;
 
352
#else
 
353
    return FALSE;
 
354
#endif
 
355
}
 
356
 
 
357
/* retrieve subject CommonName of certificate */
 
358
BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN)
 
359
{
 
360
    X509_NAME *xsn;
 
361
    X509_NAME_ENTRY *xsne;
 
362
    int i, nid;
 
363
    unsigned char *data_ptr;
 
364
    int data_len;
 
365
 
 
366
    xsn = X509_get_subject_name(xs);
 
367
    for (i = 0; i < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *)
 
368
                                           X509_NAME_get_entries(xsn)); i++) {
 
369
        xsne = sk_X509_NAME_ENTRY_value((STACK_OF(X509_NAME_ENTRY) *)
 
370
                                         X509_NAME_get_entries(xsn), i);
 
371
        nid = OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
 
372
        if (nid == NID_commonName) {
 
373
            data_ptr = X509_NAME_ENTRY_get_data_ptr(xsne);
 
374
            data_len = X509_NAME_ENTRY_get_data_len(xsne);
 
375
            *cppCN = apr_palloc(p, data_len+1);
 
376
            apr_cpystrn(*cppCN, (char *)data_ptr, data_len+1);
 
377
            (*cppCN)[data_len] = NUL;
 
378
            ap_xlate_proto_from_ascii(*cppCN, data_len);
 
379
            return TRUE;
 
380
        }
 
381
    }
 
382
    return FALSE;
 
383
}
 
384
 
 
385
/*  _________________________________________________________________
 
386
**
 
387
**  Low-Level CA Certificate Loading
 
388
**  _________________________________________________________________
 
389
*/
 
390
 
 
391
BOOL SSL_X509_INFO_load_file(apr_pool_t *ptemp,
 
392
                             STACK_OF(X509_INFO) *sk,
 
393
                             const char *filename)
 
394
{
 
395
    BIO *in;
 
396
 
 
397
    if (!(in = BIO_new(BIO_s_file()))) {
 
398
        return FALSE;
 
399
    }
 
400
 
 
401
    if (BIO_read_filename(in, MODSSL_PCHAR_CAST filename) <= 0) {
 
402
        BIO_free(in);
 
403
        return FALSE;
 
404
    }
 
405
 
 
406
    ERR_clear_error();
 
407
 
 
408
    modssl_PEM_X509_INFO_read_bio(in, sk, NULL, NULL);
 
409
 
 
410
    BIO_free(in);
 
411
 
 
412
    return TRUE;
 
413
}
 
414
 
 
415
BOOL SSL_X509_INFO_load_path(apr_pool_t *ptemp,
 
416
                             STACK_OF(X509_INFO) *sk,
 
417
                             const char *pathname)
 
418
{
 
419
    /* XXX: this dir read code is exactly the same as that in
 
420
     * ssl_engine_init.c, only the call to handle the fullname is different,
 
421
     * should fold the duplication.
 
422
     */
 
423
    apr_dir_t *dir;
 
424
    apr_finfo_t dirent;
 
425
    apr_int32_t finfo_flags = APR_FINFO_TYPE|APR_FINFO_NAME;
 
426
    const char *fullname;
 
427
    BOOL ok = FALSE;
 
428
 
 
429
    if (apr_dir_open(&dir, pathname, ptemp) != APR_SUCCESS) {
 
430
        return FALSE;
 
431
    }
 
432
 
 
433
    while ((apr_dir_read(&dirent, finfo_flags, dir)) == APR_SUCCESS) {
 
434
        if (dirent.filetype == APR_DIR) {
 
435
            continue; /* don't try to load directories */
 
436
        }
 
437
 
 
438
        fullname = apr_pstrcat(ptemp,
 
439
                               pathname, "/", dirent.name,
 
440
                               NULL);
 
441
 
 
442
        if (SSL_X509_INFO_load_file(ptemp, sk, fullname)) {
 
443
            ok = TRUE;
 
444
        }
 
445
    }
 
446
 
 
447
    apr_dir_close(dir);
 
448
 
 
449
    return ok;
 
450
}
 
451
 
 
452
/*  _________________________________________________________________
 
453
**
 
454
**  Extra Server Certificate Chain Support
 
455
**  _________________________________________________________________
 
456
*/
 
457
 
 
458
/*
 
459
 * Read a file that optionally contains the server certificate in PEM
 
460
 * format, possibly followed by a sequence of CA certificates that
 
461
 * should be sent to the peer in the SSL Certificate message.
 
462
 */
 
463
int SSL_CTX_use_certificate_chain(
 
464
    SSL_CTX *ctx, char *file, int skipfirst, modssl_read_bio_cb_fn *cb)
 
465
{
 
466
    BIO *bio;
 
467
    X509 *x509;
 
468
    unsigned long err;
 
469
    int n;
 
470
    STACK *extra_certs;
 
471
 
 
472
    if ((bio = BIO_new(BIO_s_file_internal())) == NULL)
 
473
        return -1;
 
474
    if (BIO_read_filename(bio, file) <= 0) {
 
475
        BIO_free(bio);
 
476
        return -1;
 
477
    }
 
478
    /* optionally skip a leading server certificate */
 
479
    if (skipfirst) {
 
480
        if ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) {
 
481
            BIO_free(bio);
 
482
            return -1;
 
483
        }
 
484
        X509_free(x509);
 
485
    }
 
486
    /* free a perhaps already configured extra chain */
 
487
    extra_certs=SSL_CTX_get_extra_certs(ctx);
 
488
    if (extra_certs != NULL) {
 
489
        sk_X509_pop_free((STACK_OF(X509) *)extra_certs, X509_free);
 
490
        SSL_CTX_set_extra_certs(ctx,NULL);
 
491
    }
 
492
    /* create new extra chain by loading the certs */
 
493
    n = 0;
 
494
    while ((x509 = modssl_PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
 
495
        if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
 
496
            X509_free(x509);
 
497
            BIO_free(bio);
 
498
            return -1;
 
499
        }
 
500
        n++;
 
501
    }
 
502
    /* Make sure that only the error is just an EOF */
 
503
    if ((err = ERR_peek_error()) > 0) {
 
504
        if (!(   ERR_GET_LIB(err) == ERR_LIB_PEM
 
505
              && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
 
506
            BIO_free(bio);
 
507
            return -1;
 
508
        }
 
509
        while (ERR_get_error() > 0) ;
 
510
    }
 
511
    BIO_free(bio);
 
512
    return n;
 
513
}
 
514
 
 
515
/*  _________________________________________________________________
 
516
**
 
517
**  Session Stuff
 
518
**  _________________________________________________________________
 
519
*/
 
520
 
 
521
char *SSL_SESSION_id2sz(unsigned char *id, int idlen,
 
522
                        char *str, int strsize)
 
523
{
 
524
    char *cp;
 
525
    int n;
 
526
 
 
527
    cp = str;
 
528
    for (n = 0; n < idlen && n < SSL_MAX_SSL_SESSION_ID_LENGTH; n++) {
 
529
        apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]);
 
530
        cp += 2;
 
531
    }
 
532
    *cp = NUL;
 
533
    return str;
 
534
}
 
535
 
 
536
/* sslc+OpenSSL compat */
 
537
 
 
538
int modssl_session_get_time(SSL_SESSION *session)
 
539
{
 
540
#ifdef OPENSSL_VERSION_NUMBER
 
541
    return SSL_SESSION_get_time(session);
 
542
#else /* assume sslc */
 
543
    CRYPTO_TIME_T ct;
 
544
    SSL_SESSION_get_time(session, &ct);
 
545
    return CRYPTO_time_to_int(&ct);
 
546
#endif
 
547
}
 
548
 
 
549
#ifndef SSLC_VERSION_NUMBER
 
550
#define SSLC_VERSION_NUMBER 0x0000
 
551
#endif
 
552
 
 
553
DH *modssl_dh_configure(unsigned char *p, int plen,
 
554
                        unsigned char *g, int glen)
 
555
{
 
556
    DH *dh;
 
557
 
 
558
    if (!(dh = DH_new())) {
 
559
        return NULL;
 
560
    }
 
561
 
 
562
#if defined(OPENSSL_VERSION_NUMBER) || (SSLC_VERSION_NUMBER < 0x2000)
 
563
    dh->p = BN_bin2bn(p, plen, NULL);
 
564
    dh->g = BN_bin2bn(g, glen, NULL);
 
565
    if (!(dh->p && dh->g)) {
 
566
        DH_free(dh);
 
567
        return NULL;
 
568
    }
 
569
#else
 
570
    R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_P, 0, p, plen, R_EITEMS_PF_COPY);
 
571
    R_EITEMS_add(dh->data, PK_TYPE_DH, PK_DH_G, 0, g, glen, R_EITEMS_PF_COPY);
 
572
#endif
 
573
 
 
574
    return dh;
 
575
}