195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This package is an SSL implementation written
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * by Eric Young (eay@cryptsoft.com).
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The implementation was written so as to conform with Netscapes SSL.
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This library is free for commercial and non-commercial use as long as
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the following conditions are aheared to.  The following conditions
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * apply to all code found in this distribution, be it the RC4, RSA,
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * included with this distribution is covered by the same copyright terms
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * the code are not to be removed.
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * If this package is used in a product, Eric Young should be given attribution
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * as the author of the parts of the library used.
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * This can be in the form of a textual message at program startup or
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * in documentation (online or textual) provided with the package.
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the copyright
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 3. All advertising materials mentioning features or use of this software
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    must display the following acknowledgement:
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes cryptographic software written by
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *     Eric Young (eay@cryptsoft.com)"
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    The word 'cryptographic' can be left out if the rouines from the library
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    being used are not cryptographic related :-).
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    the apps directory (application code) you must include an acknowledgement:
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SUCH DAMAGE.
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The licence and distribution terms for any publically available version or
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * copied and put under another distribution licence
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * [including the GNU Public Licence.]
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * The DSS routines are based on patches supplied by
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/dsa.h>
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/asn1.h>
63bed8ce78f001c600a143966b932f8e587c35e573Adam Langley#include <openssl/dh.h>
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/engine.h>
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/err.h>
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/ex_data.h>
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <openssl/mem.h>
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "internal.h"
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyextern const DSA_METHOD DSA_default_method;
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyDSA *DSA_new(void) { return DSA_new_method(NULL); }
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyDSA *DSA_new_method(const ENGINE *engine) {
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA));
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa == NULL) {
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_PUT_ERROR(DSA, DSA_new_method, ERR_R_MALLOC_FAILURE);
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return NULL;
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  memset(dsa, 0, sizeof(DSA));
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (engine) {
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dsa->meth = ENGINE_get_DSA_method(engine);
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth == NULL) {
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dsa->meth = (DSA_METHOD*) &DSA_default_method;
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  METHOD_ref(dsa->meth);
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dsa->write_params = 1;
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  dsa->references = 1;
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data)) {
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    METHOD_unref(dsa->meth);
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(dsa);
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return NULL;
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->init && !dsa->meth->init(dsa)) {
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    METHOD_unref(dsa->meth);
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    OPENSSL_free(dsa);
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return NULL;
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return dsa;
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid DSA_free(DSA *dsa) {
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa == NULL) {
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (CRYPTO_add(&dsa->references, -1, CRYPTO_LOCK_DSA) > 0) {
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->finish) {
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    dsa->meth->finish(dsa);
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  METHOD_unref(dsa->meth);
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data);
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->p != NULL)
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->p);
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->q != NULL)
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->q);
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->g != NULL)
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->g);
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->pub_key != NULL)
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->pub_key);
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->priv_key != NULL)
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->priv_key);
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->kinv != NULL)
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->kinv);
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->r != NULL)
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_clear_free(dsa->r);
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  OPENSSL_free(dsa);
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_up_ref(DSA *dsa) {
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  CRYPTO_add(&dsa->references, 1, CRYPTO_LOCK_DSA);
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                               size_t seed_len, int *out_counter,
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                               unsigned long *out_h, BN_GENCB *cb) {
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->generate_parameters) {
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return dsa->meth->generate_parameters(dsa, bits, seed_in, seed_len,
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                          out_counter, out_h, cb);
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return DSA_default_method.generate_parameters(dsa, bits, seed_in, seed_len,
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                                out_counter, out_h, cb);
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_generate_key(DSA *dsa) {
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->keygen) {
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return dsa->meth->keygen(dsa);
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return DSA_default_method.keygen(dsa);
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyDSA_SIG *DSA_SIG_new(void) {
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA_SIG *sig;
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  sig = OPENSSL_malloc(sizeof(DSA_SIG));
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!sig) {
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return NULL;
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  sig->r = NULL;
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  sig->s = NULL;
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return sig;
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid DSA_SIG_free(DSA_SIG *sig) {
18095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!sig) {
18195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (sig->r) {
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_free(sig->r);
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (sig->s) {
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    BN_free(sig->s);
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  OPENSSL_free(sig);
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyDSA_SIG *DSA_do_sign(const uint8_t *digest, size_t digest_len, DSA *dsa) {
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->sign) {
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return dsa->meth->sign(digest, digest_len, dsa);
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return DSA_default_method.sign(digest, digest_len, dsa);
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_do_verify(const uint8_t *digest, size_t digest_len, DSA_SIG *sig,
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                  const DSA *dsa) {
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int valid, ret;
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->verify) {
20595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ret = dsa->meth->verify(&valid, digest, digest_len, sig, dsa);
20695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
20795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ret = DSA_default_method.verify(&valid, digest, digest_len, sig, dsa);
20895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
20995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!ret) {
21195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return -1;
21295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else if (!valid) {
21395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
21495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
21595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
21695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
21795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
21895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_do_check_signature(int *out_valid, const uint8_t *digest,
21995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
22095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->verify) {
22195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return dsa->meth->verify(out_valid, digest, digest_len, sig, dsa);
22295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
22395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return DSA_default_method.verify(out_valid, digest, digest_len, sig, dsa);
22595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
22695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
22795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_sign(int type, const uint8_t *digest, size_t digest_len,
22895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley             uint8_t *out_sig, unsigned int *out_siglen, DSA *dsa) {
22995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA_SIG *s;
23095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  s = DSA_do_sign(digest, digest_len, dsa);
23295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (s == NULL) {
23395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *out_siglen = 0;
23495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
23595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
23695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
23795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  *out_siglen = i2d_DSA_SIG(s, &out_sig);
23895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA_SIG_free(s);
23995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 1;
24095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
24195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_verify(int type, const uint8_t *digest, size_t digest_len,
24395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley               const uint8_t *sig, size_t sig_len, const DSA *dsa) {
24495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA_SIG *s = NULL;
24595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int ret = -1, valid;
24695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
24795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  s = DSA_SIG_new();
24895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (s == NULL) {
24995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto err;
25095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
25195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (d2i_DSA_SIG(&s, &sig, sig_len) == NULL) {
25395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto err;
25495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
25595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
25695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!DSA_do_check_signature(&valid, digest, digest_len, s, dsa)) {
25795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto err;
25895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
25995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ret = valid;
26195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr:
26395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (s) {
26495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    DSA_SIG_free(s);
26595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
26695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
26795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
26895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
26995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_check_signature(int *out_valid, const uint8_t *digest,
27095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                        size_t digest_len, const uint8_t *sig, size_t sig_len,
27195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                        const DSA *dsa) {
27295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  DSA_SIG *s = NULL;
27395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int ret = 0;
27495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
27595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  s = DSA_SIG_new();
27695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (s == NULL) {
27795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto err;
27895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
27995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (d2i_DSA_SIG(&s, &sig, sig_len) == NULL) {
28195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    goto err;
28295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
28395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ret = DSA_do_check_signature(out_valid, digest, digest_len, s, dsa);
28595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
28695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyerr:
28795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (s) {
28895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    DSA_SIG_free(s);
28995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
29095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
29195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
29295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
29395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_size(const DSA *dsa) {
29495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  int ret, i;
29595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ASN1_INTEGER bs;
29695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  unsigned char buf[4]; /* 4 bytes looks really small.
29795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           However, i2d_ASN1_INTEGER() will not look
29895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           beyond the first byte, as long as the second
29995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                           parameter is NULL. */
30095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  i = BN_num_bits(dsa->q);
30295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bs.length = (i + 7) / 8;
30395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bs.data = buf;
30495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bs.type = V_ASN1_INTEGER;
30595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  /* If the top bit is set the asn1 encoding is 1 larger. */
30695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  buf[0] = 0xff;
30795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
30895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  i = i2d_ASN1_INTEGER(&bs, NULL);
30995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  i += i; /* r and s */
31095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
31195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return ret;
31295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
31395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
31495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_sign_setup(const DSA *dsa, BN_CTX *ctx, BIGNUM **out_kinv,
31595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                   BIGNUM **out_r) {
31695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (dsa->meth->sign_setup) {
317d4b4f085d9c8bf0ae28769e53cceb2b47a2b34fbAdam Langley    return dsa->meth->sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
31895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
31995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
320d4b4f085d9c8bf0ae28769e53cceb2b47a2b34fbAdam Langley  return DSA_default_method.sign_setup(dsa, ctx, out_kinv, out_r, NULL, 0);
32195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
32295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
32495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                         CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
32595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp, new_func,
32695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                 dup_func, free_func);
32795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
32895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
32995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint DSA_set_ex_data(DSA *d, int idx, void *arg) {
33095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
33195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
33295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
33395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid *DSA_get_ex_data(const DSA *d, int idx) {
33495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return CRYPTO_get_ex_data(&d->ex_data, idx);
33595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
336bed8ce78f001c600a143966b932f8e587c35e573Adam Langley
337bed8ce78f001c600a143966b932f8e587c35e573Adam LangleyDH *DSA_dup_DH(const DSA *r) {
338bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  DH *ret = NULL;
339bed8ce78f001c600a143966b932f8e587c35e573Adam Langley
340bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  if (r == NULL) {
341bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    goto err;
342bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  }
343bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  ret = DH_new();
344bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  if (ret == NULL) {
345bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    goto err;
346bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  }
347bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  if (r->q != NULL) {
348bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    ret->priv_length = BN_num_bits(r->q);
349bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    if ((ret->q = BN_dup(r->q)) == NULL) {
350bed8ce78f001c600a143966b932f8e587c35e573Adam Langley      goto err;
351bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    }
352bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  }
353bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) ||
354bed8ce78f001c600a143966b932f8e587c35e573Adam Langley      (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) ||
355bed8ce78f001c600a143966b932f8e587c35e573Adam Langley      (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) ||
356bed8ce78f001c600a143966b932f8e587c35e573Adam Langley      (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) {
357bed8ce78f001c600a143966b932f8e587c35e573Adam Langley      goto err;
358bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  }
359bed8ce78f001c600a143966b932f8e587c35e573Adam Langley
360bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  return ret;
361bed8ce78f001c600a143966b932f8e587c35e573Adam Langley
362bed8ce78f001c600a143966b932f8e587c35e573Adam Langleyerr:
363bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  if (ret != NULL) {
364bed8ce78f001c600a143966b932f8e587c35e573Adam Langley    DH_free(ret);
365bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  }
366bed8ce78f001c600a143966b932f8e587c35e573Adam Langley  return NULL;
367bed8ce78f001c600a143966b932f8e587c35e573Adam Langley}
368