der2dsa.c 3.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/* der2dsa.c
 *
 * Decoding of DSA keys in OpenSSL and X509.1 format.
 */

/* nettle, low-level cryptographics library
 *
 * Copyright (C) 2005, 2009 Niels Mller, Magnus Holmgren
 *  
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * The nettle library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 * MA 02111-1307, USA.
 */

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include "dsa.h"

#include "bignum.h"
#include "asn1.h"

#define GET(i, x, l)					\
(asn1_der_iterator_next((i)) == ASN1_ITERATOR_PRIMITIVE	\
 && (i)->type == ASN1_INTEGER				\
 && asn1_der_get_bignum((i), (x), (l))			\
 && mpz_sgn((x)) > 0)

int
dsa_public_key_from_der_iterators(struct dsa_public_key *pub,
				 unsigned limit,
				 struct asn1_der_iterator *i,
				 struct asn1_der_iterator *j)
{
  /* DSAPublicKey ::= INTEGER
     Dss-Parms ::= SEQUENCE {
	 p  INTEGER,
	 q  INTEGER,
	 g  INTEGER
     }
  */

  return (i->type == ASN1_INTEGER
	  && asn1_der_get_bignum(i, pub->y, limit)
	  && mpz_sgn(pub->y) > 0
	  && j->type == ASN1_INTEGER
	  && asn1_der_get_bignum(j, pub->p, limit)
	  && mpz_sgn(pub->p) > 0
	  && GET(j, pub->q, limit)
	  && GET(j, pub->g, limit)
	  && asn1_der_iterator_next(i) == ASN1_ITERATOR_END);
}

/* FIXME: Rename this and the next function to something
   openssl-specific? */
int
dsa_private_key_from_der_iterator(struct dsa_public_key *pub,
				  struct dsa_private_key *priv,
				  unsigned limit,
				  struct asn1_der_iterator *i)
{
  /* DSAPrivateKey ::= SEQUENCE {
         version           Version,
	 p                 INTEGER,
	 q                 INTEGER,
	 g                 INTEGER,
	 pub_key           INTEGER,  -- y
	 priv_key          INTEGER,  -- x
    }
  */

  uint32_t version;
  
  return (i->type == ASN1_SEQUENCE
87
	  && asn1_der_decode_constructed_last(i) == ASN1_ITERATOR_PRIMITIVE
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
	  && i->type == ASN1_INTEGER
	  && asn1_der_get_uint32(i, &version)
	  && version == 0
	  && GET(i, pub->p, limit)
	  && GET(i, pub->q, limit)
	  && GET(i, pub->g, limit)
	  && GET(i, pub->y, limit)
	  && GET(i, priv->x, limit)
	  && asn1_der_iterator_next(i) == ASN1_ITERATOR_END);
}

int
dsa_keypair_from_der(struct dsa_public_key *pub,
		     struct dsa_private_key *priv,
		     unsigned limit,
		     unsigned length, const uint8_t *data)
{
  struct asn1_der_iterator i;
  enum asn1_iterator_result res;

  res = asn1_der_iterator_first(&i, length, data);

  if (res != ASN1_ITERATOR_CONSTRUCTED)
    return 0;

  if (priv)
    return dsa_private_key_from_der_iterator(pub, priv, limit, &i);
  else
    return 0;
}