11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci/*
111cb0ef41Sopenharmony_ci * DH low level APIs are deprecated for public use, but still ok for
121cb0ef41Sopenharmony_ci * internal use.
131cb0ef41Sopenharmony_ci */
141cb0ef41Sopenharmony_ci#include "internal/deprecated.h"
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#include <stdio.h>
171cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
181cb0ef41Sopenharmony_ci#include <openssl/bn.h>
191cb0ef41Sopenharmony_ci#include "dh_local.h"
201cb0ef41Sopenharmony_ci#include <openssl/objects.h>
211cb0ef41Sopenharmony_ci#include <openssl/asn1t.h>
221cb0ef41Sopenharmony_ci#include "crypto/dh.h"
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci/* Override the default free and new methods */
251cb0ef41Sopenharmony_cistatic int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
261cb0ef41Sopenharmony_ci                 void *exarg)
271cb0ef41Sopenharmony_ci{
281cb0ef41Sopenharmony_ci    if (operation == ASN1_OP_NEW_PRE) {
291cb0ef41Sopenharmony_ci        *pval = (ASN1_VALUE *)DH_new();
301cb0ef41Sopenharmony_ci        if (*pval != NULL)
311cb0ef41Sopenharmony_ci            return 2;
321cb0ef41Sopenharmony_ci        return 0;
331cb0ef41Sopenharmony_ci    } else if (operation == ASN1_OP_FREE_PRE) {
341cb0ef41Sopenharmony_ci        DH_free((DH *)*pval);
351cb0ef41Sopenharmony_ci        *pval = NULL;
361cb0ef41Sopenharmony_ci        return 2;
371cb0ef41Sopenharmony_ci    } else if (operation == ASN1_OP_D2I_POST) {
381cb0ef41Sopenharmony_ci        DH *dh = (DH *)*pval;
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci        DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
411cb0ef41Sopenharmony_ci        DH_set_flags(dh, DH_FLAG_TYPE_DH);
421cb0ef41Sopenharmony_ci        ossl_dh_cache_named_group(dh);
431cb0ef41Sopenharmony_ci        dh->dirty_cnt++;
441cb0ef41Sopenharmony_ci    }
451cb0ef41Sopenharmony_ci    return 1;
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciASN1_SEQUENCE_cb(DHparams, dh_cb) = {
491cb0ef41Sopenharmony_ci        ASN1_SIMPLE(DH, params.p, BIGNUM),
501cb0ef41Sopenharmony_ci        ASN1_SIMPLE(DH, params.g, BIGNUM),
511cb0ef41Sopenharmony_ci        ASN1_OPT_EMBED(DH, length, ZINT32),
521cb0ef41Sopenharmony_ci} ASN1_SEQUENCE_END_cb(DH, DHparams)
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DH, DHparams, DHparams)
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci/*
571cb0ef41Sopenharmony_ci * Internal only structures for handling X9.42 DH: this gets translated to or
581cb0ef41Sopenharmony_ci * from a DH structure straight away.
591cb0ef41Sopenharmony_ci */
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_citypedef struct {
621cb0ef41Sopenharmony_ci    ASN1_BIT_STRING *seed;
631cb0ef41Sopenharmony_ci    BIGNUM *counter;
641cb0ef41Sopenharmony_ci} int_dhvparams;
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_citypedef struct {
671cb0ef41Sopenharmony_ci    BIGNUM *p;
681cb0ef41Sopenharmony_ci    BIGNUM *q;
691cb0ef41Sopenharmony_ci    BIGNUM *g;
701cb0ef41Sopenharmony_ci    BIGNUM *j;
711cb0ef41Sopenharmony_ci    int_dhvparams *vparams;
721cb0ef41Sopenharmony_ci} int_dhx942_dh;
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ciASN1_SEQUENCE(DHvparams) = {
751cb0ef41Sopenharmony_ci        ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING),
761cb0ef41Sopenharmony_ci        ASN1_SIMPLE(int_dhvparams, counter, BIGNUM)
771cb0ef41Sopenharmony_ci} static_ASN1_SEQUENCE_END_name(int_dhvparams, DHvparams)
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ciASN1_SEQUENCE(DHxparams) = {
801cb0ef41Sopenharmony_ci        ASN1_SIMPLE(int_dhx942_dh, p, BIGNUM),
811cb0ef41Sopenharmony_ci        ASN1_SIMPLE(int_dhx942_dh, g, BIGNUM),
821cb0ef41Sopenharmony_ci        ASN1_SIMPLE(int_dhx942_dh, q, BIGNUM),
831cb0ef41Sopenharmony_ci        ASN1_OPT(int_dhx942_dh, j, BIGNUM),
841cb0ef41Sopenharmony_ci        ASN1_OPT(int_dhx942_dh, vparams, DHvparams),
851cb0ef41Sopenharmony_ci} static_ASN1_SEQUENCE_END_name(int_dhx942_dh, DHxparams)
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciint_dhx942_dh *d2i_int_dhx(int_dhx942_dh **a,
881cb0ef41Sopenharmony_ci                           const unsigned char **pp, long length);
891cb0ef41Sopenharmony_ciint i2d_int_dhx(const int_dhx942_dh *a, unsigned char **pp);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(int_dhx942_dh, DHxparams, int_dhx)
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ciDH *d2i_DHxparams(DH **a, const unsigned char **pp, long length)
941cb0ef41Sopenharmony_ci{
951cb0ef41Sopenharmony_ci    FFC_PARAMS *params;
961cb0ef41Sopenharmony_ci    int_dhx942_dh *dhx = NULL;
971cb0ef41Sopenharmony_ci    DH *dh = NULL;
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci    dh = DH_new();
1001cb0ef41Sopenharmony_ci    if (dh == NULL)
1011cb0ef41Sopenharmony_ci        return NULL;
1021cb0ef41Sopenharmony_ci    dhx = d2i_int_dhx(NULL, pp, length);
1031cb0ef41Sopenharmony_ci    if (dhx == NULL) {
1041cb0ef41Sopenharmony_ci        DH_free(dh);
1051cb0ef41Sopenharmony_ci        return NULL;
1061cb0ef41Sopenharmony_ci    }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci    if (a != NULL) {
1091cb0ef41Sopenharmony_ci        DH_free(*a);
1101cb0ef41Sopenharmony_ci        *a = dh;
1111cb0ef41Sopenharmony_ci    }
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci    params = &dh->params;
1141cb0ef41Sopenharmony_ci    DH_set0_pqg(dh, dhx->p, dhx->q, dhx->g);
1151cb0ef41Sopenharmony_ci    ossl_ffc_params_set0_j(params, dhx->j);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci    if (dhx->vparams != NULL) {
1181cb0ef41Sopenharmony_ci        /* The counter has a maximum value of 4 * numbits(p) - 1 */
1191cb0ef41Sopenharmony_ci        size_t counter = (size_t)BN_get_word(dhx->vparams->counter);
1201cb0ef41Sopenharmony_ci        ossl_ffc_params_set_validate_params(params, dhx->vparams->seed->data,
1211cb0ef41Sopenharmony_ci                                            dhx->vparams->seed->length,
1221cb0ef41Sopenharmony_ci                                            counter);
1231cb0ef41Sopenharmony_ci        ASN1_BIT_STRING_free(dhx->vparams->seed);
1241cb0ef41Sopenharmony_ci        BN_free(dhx->vparams->counter);
1251cb0ef41Sopenharmony_ci        OPENSSL_free(dhx->vparams);
1261cb0ef41Sopenharmony_ci        dhx->vparams = NULL;
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci    OPENSSL_free(dhx);
1301cb0ef41Sopenharmony_ci    DH_clear_flags(dh, DH_FLAG_TYPE_MASK);
1311cb0ef41Sopenharmony_ci    DH_set_flags(dh, DH_FLAG_TYPE_DHX);
1321cb0ef41Sopenharmony_ci    return dh;
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ciint i2d_DHxparams(const DH *dh, unsigned char **pp)
1361cb0ef41Sopenharmony_ci{
1371cb0ef41Sopenharmony_ci    int ret = 0;
1381cb0ef41Sopenharmony_ci    int_dhx942_dh dhx;
1391cb0ef41Sopenharmony_ci    int_dhvparams dhv = { NULL, NULL };
1401cb0ef41Sopenharmony_ci    ASN1_BIT_STRING seed;
1411cb0ef41Sopenharmony_ci    size_t seedlen = 0;
1421cb0ef41Sopenharmony_ci    const FFC_PARAMS *params = &dh->params;
1431cb0ef41Sopenharmony_ci    int counter;
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci    ossl_ffc_params_get0_pqg(params, (const BIGNUM **)&dhx.p,
1461cb0ef41Sopenharmony_ci                             (const BIGNUM **)&dhx.q, (const BIGNUM **)&dhx.g);
1471cb0ef41Sopenharmony_ci    dhx.j = params->j;
1481cb0ef41Sopenharmony_ci    ossl_ffc_params_get_validate_params(params, &seed.data, &seedlen, &counter);
1491cb0ef41Sopenharmony_ci    seed.length = (int)seedlen;
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci    if (counter != -1 && seed.data != NULL && seed.length > 0) {
1521cb0ef41Sopenharmony_ci        seed.flags = ASN1_STRING_FLAG_BITS_LEFT;
1531cb0ef41Sopenharmony_ci        dhv.seed = &seed;
1541cb0ef41Sopenharmony_ci        dhv.counter = BN_new();
1551cb0ef41Sopenharmony_ci        if (dhv.counter == NULL)
1561cb0ef41Sopenharmony_ci            return 0;
1571cb0ef41Sopenharmony_ci        if (!BN_set_word(dhv.counter, (BN_ULONG)counter))
1581cb0ef41Sopenharmony_ci            goto err;
1591cb0ef41Sopenharmony_ci        dhx.vparams = &dhv;
1601cb0ef41Sopenharmony_ci    } else {
1611cb0ef41Sopenharmony_ci        dhx.vparams = NULL;
1621cb0ef41Sopenharmony_ci    }
1631cb0ef41Sopenharmony_ci    ret = i2d_int_dhx(&dhx, pp);
1641cb0ef41Sopenharmony_cierr:
1651cb0ef41Sopenharmony_ci    BN_free(dhv.counter);
1661cb0ef41Sopenharmony_ci    return ret;
1671cb0ef41Sopenharmony_ci}
168