dh_asn1.c 3.6 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
D
Dr. Stephen Henson 已提交
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
D
Dr. Stephen Henson 已提交
8 9 10
 */

#include <stdio.h>
11
#include "internal/cryptlib.h"
D
 
Dr. Stephen Henson 已提交
12
#include <openssl/bn.h>
M
Matt Caswell 已提交
13
#include "dh_locl.h"
D
 
Dr. Stephen Henson 已提交
14 15
#include <openssl/objects.h>
#include <openssl/asn1t.h>
D
Dr. Stephen Henson 已提交
16

D
 
Dr. Stephen Henson 已提交
17
/* Override the default free and new methods */
18
static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
19
                 void *exarg)
D
Dr. Stephen Henson 已提交
20
{
21 22
    if (operation == ASN1_OP_NEW_PRE) {
        *pval = (ASN1_VALUE *)DH_new();
23
        if (*pval != NULL)
24 25 26 27 28 29 30 31
            return 2;
        return 0;
    } else if (operation == ASN1_OP_FREE_PRE) {
        DH_free((DH *)*pval);
        *pval = NULL;
        return 2;
    }
    return 1;
D
Dr. Stephen Henson 已提交
32 33
}

D
 
Dr. Stephen Henson 已提交
34
ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
35 36
        ASN1_SIMPLE(DH, p, BIGNUM),
        ASN1_SIMPLE(DH, g, BIGNUM),
37
        ASN1_OPT_EMBED(DH, length, ZINT32),
R
Rich Salz 已提交
38
} ASN1_SEQUENCE_END_cb(DH, DHparams)
D
 
Dr. Stephen Henson 已提交
39 40

IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
D
Dr. Stephen Henson 已提交
41

42 43 44
/*
 * Internal only structures for handling X9.42 DH: this gets translated to or
 * from a DH structure straight away.
45 46
 */

47 48 49 50 51 52 53 54 55 56 57 58
typedef struct {
    ASN1_BIT_STRING *seed;
    BIGNUM *counter;
} int_dhvparams;

typedef struct {
    BIGNUM *p;
    BIGNUM *q;
    BIGNUM *g;
    BIGNUM *j;
    int_dhvparams *vparams;
} int_dhx942_dh;
59 60

ASN1_SEQUENCE(DHvparams) = {
61 62
        ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
        ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
63
} static_ASN1_SEQUENCE_END_name(int_dhvparams, DHvparams)
64 65

ASN1_SEQUENCE(DHxparams) = {
66 67 68 69 70
        ASN1_SIMPLE(int_dhx942_dh, p, BIGNUM),
        ASN1_SIMPLE(int_dhx942_dh, g, BIGNUM),
        ASN1_SIMPLE(int_dhx942_dh, q, BIGNUM),
        ASN1_OPT(int_dhx942_dh, j, BIGNUM),
        ASN1_OPT(int_dhx942_dh, vparams, DHvparams),
71
} static_ASN1_SEQUENCE_END_name(int_dhx942_dh, DHxparams)
72

73 74 75
int_dhx942_dh *d2i_int_dhx(int_dhx942_dh **a,
                           const unsigned char **pp, long length);
int i2d_int_dhx(const int_dhx942_dh *a, unsigned char **pp);
76 77 78

IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(int_dhx942_dh, DHxparams, int_dhx)

F
FdaSilvaYY 已提交
79
/* Application public function: read in X9.42 DH parameters into DH structure */
80

81 82 83 84 85
DH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
{
    int_dhx942_dh *dhx = NULL;
    DH *dh = NULL;
    dh = DH_new();
86
    if (dh == NULL)
87 88
        return NULL;
    dhx = d2i_int_dhx(NULL, pp, length);
89
    if (dhx == NULL) {
90 91 92 93 94
        DH_free(dh);
        return NULL;
    }

    if (a) {
R
Rich Salz 已提交
95
        DH_free(*a);
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
        *a = dh;
    }

    dh->p = dhx->p;
    dh->q = dhx->q;
    dh->g = dhx->g;
    dh->j = dhx->j;

    if (dhx->vparams) {
        dh->seed = dhx->vparams->seed->data;
        dh->seedlen = dhx->vparams->seed->length;
        dh->counter = dhx->vparams->counter;
        dhx->vparams->seed->data = NULL;
        ASN1_BIT_STRING_free(dhx->vparams->seed);
        OPENSSL_free(dhx->vparams);
        dhx->vparams = NULL;
    }

    OPENSSL_free(dhx);
    return dh;
}

int i2d_DHxparams(const DH *dh, unsigned char **pp)
{
    int_dhx942_dh dhx;
    int_dhvparams dhv;
    ASN1_BIT_STRING bs;
    dhx.p = dh->p;
    dhx.g = dh->g;
    dhx.q = dh->q;
    dhx.j = dh->j;
    if (dh->counter && dh->seed && dh->seedlen > 0) {
        bs.flags = ASN1_STRING_FLAG_BITS_LEFT;
        bs.data = dh->seed;
        bs.length = dh->seedlen;
        dhv.seed = &bs;
        dhv.counter = dh->counter;
        dhx.vparams = &dhv;
    } else
        dhx.vparams = NULL;

    return i2d_int_dhx(&dhx, pp);
}