Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@chromium.org>2016-01-30 09:51:01 +0300
committerAdam Langley <agl@google.com>2016-02-17 03:26:01 +0300
commitfda22a75730d8982baf8a567201f6254d47c9572 (patch)
tree53a33e5ed4a12f24849b7836f56c2fe6cb84873c /crypto
parent3cadf63c68c26c2f5df2f6f2a1358db4772f0163 (diff)
Reimplement DSA parsing logic with crypto/asn1.
Functions which lose object reuse and need auditing: - d2i_DSA_SIG - d2i_DSAPublicKey - d2i_DSAPrivateKey - d2i_DSAparams BUG=499653 Change-Id: I1cc2ae10e1e77eb57da3a858ac8734a95715ce4b Reviewed-on: https://boringssl-review.googlesource.com/7022 Reviewed-by: Adam Langley <agl@google.com>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/dsa/dsa.c15
-rw-r--r--crypto/dsa/dsa_asn1.c306
-rw-r--r--crypto/err/dsa.errordata3
3 files changed, 269 insertions, 55 deletions
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index 2a9524a3..3b269d4f 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -392,6 +392,21 @@ err:
return ok;
}
+DSA *DSAparams_dup(const DSA *dsa) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ ret->p = BN_dup(dsa->p);
+ ret->q = BN_dup(dsa->q);
+ ret->g = BN_dup(dsa->g);
+ if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
int DSA_generate_key(DSA *dsa) {
int ok = 0;
BN_CTX *ctx = NULL;
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
index 4df561d6..d7b826cc 100644
--- a/crypto/dsa/dsa_asn1.c
+++ b/crypto/dsa/dsa_asn1.c
@@ -54,87 +54,283 @@
#include <openssl/dsa.h>
-#include <string.h>
+#include <assert.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include "internal.h"
+#include "../bytestring/internal.h"
-static int dsa_sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg) {
- if (operation != ASN1_OP_NEW_PRE) {
- return 1;
+static int parse_integer(CBS *cbs, BIGNUM **out) {
+ assert(*out == NULL);
+ *out = BN_new();
+ if (*out == NULL) {
+ return 0;
+ }
+ return BN_parse_asn1_unsigned(cbs, *out);
+}
+
+static int marshal_integer(CBB *cbb, BIGNUM *bn) {
+ if (bn == NULL) {
+ /* A DSA object may be missing some components. */
+ OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ return BN_marshal_asn1(cbb, bn);
+}
+
+DSA_SIG *DSA_SIG_parse(CBS *cbs) {
+ DSA_SIG *ret = DSA_SIG_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->r) ||
+ !parse_integer(&child, &ret->s) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_SIG_free(ret);
+ return NULL;
}
+ return ret;
+}
- DSA_SIG *sig;
- sig = OPENSSL_malloc(sizeof(DSA_SIG));
- if (!sig) {
- OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE);
+int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, sig->r) ||
+ !marshal_integer(&child, sig->s) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
return 0;
}
+ return 1;
+}
+
+DSA *DSA_parse_public_key(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->pub_key) ||
+ !parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
- memset(sig, 0, sizeof(DSA_SIG));
- *pval = (ASN1_VALUE *)sig;
- return 2;
+int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, dsa->pub_key) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
}
-ASN1_SEQUENCE_cb(DSA_SIG, dsa_sig_cb) = {
- ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
- ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG);
+DSA *DSA_parse_parameters(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
+ CBS child;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ DSA_free(ret);
+ return NULL;
+ }
+ return ret;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG);
+int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
+}
+DSA *DSA_parse_private_key(CBS *cbs) {
+ DSA *ret = DSA_new();
+ if (ret == NULL) {
+ return NULL;
+ }
-static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
- void *exarg) {
- switch (operation) {
- case ASN1_OP_NEW_PRE:
- *pval = (ASN1_VALUE *)DSA_new();
- if (*pval) {
- return 2;
- }
- return 0;
+ CBS child;
+ uint64_t version;
+ if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&child, &version)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ goto err;
+ }
- case ASN1_OP_FREE_PRE:
- DSA_free((DSA *)*pval);
- *pval = NULL;
- return 2;
+ if (version != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
+ goto err;
+ }
- default:
- return 1;
+ if (!parse_integer(&child, &ret->p) ||
+ !parse_integer(&child, &ret->q) ||
+ !parse_integer(&child, &ret->g) ||
+ !parse_integer(&child, &ret->pub_key) ||
+ !parse_integer(&child, &ret->priv_key) ||
+ CBS_len(&child) != 0) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+ goto err;
}
+ return ret;
+
+err:
+ DSA_free(ret);
+ return NULL;
}
-ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
- ASN1_SIMPLE(DSA, version, LONG),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM),
- ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_SIMPLE(DSA, priv_key, BIGNUM)} ASN1_SEQUENCE_END_cb(DSA,
- DSAPrivateKey);
+int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
+ CBB child;
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&child, 0 /* version */) ||
+ !marshal_integer(&child, dsa->p) ||
+ !marshal_integer(&child, dsa->q) ||
+ !marshal_integer(&child, dsa->g) ||
+ !marshal_integer(&child, dsa->pub_key) ||
+ !marshal_integer(&child, dsa->priv_key) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+ return 0;
+ }
+ return 1;
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey);
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA_SIG *ret = DSA_SIG_parse(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out_sig != NULL) {
+ DSA_SIG_free(*out_sig);
+ *out_sig = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
- ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM), } ASN1_SEQUENCE_END_cb(DSA, DSAparams);
+int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_SIG_marshal(&cbb, in)) {
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams);
+DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_public_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
-ASN1_SEQUENCE_cb(DSAPublicKey, dsa_cb) = {
- ASN1_SIMPLE(DSA, pub_key, BIGNUM),
- ASN1_SIMPLE(DSA, p, BIGNUM),
- ASN1_SIMPLE(DSA, q, BIGNUM),
- ASN1_SIMPLE(DSA, g, BIGNUM)
-} ASN1_SEQUENCE_END_cb(DSA, DSAPublicKey);
+int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_public_key(&cbb, in)) {
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey);
+DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_private_key(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
+
+int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_private_key(&cbb, in)) {
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
+}
-DSA *DSAparams_dup(const DSA *dsa) {
- return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), (DSA*) dsa);
+DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) {
+ if (len < 0) {
+ return NULL;
+ }
+ CBS cbs;
+ CBS_init(&cbs, *inp, (size_t)len);
+ DSA *ret = DSA_parse_parameters(&cbs);
+ if (ret == NULL) {
+ return NULL;
+ }
+ if (out != NULL) {
+ DSA_free(*out);
+ *out = ret;
+ }
+ *inp = CBS_data(&cbs);
+ return ret;
+}
+
+int i2d_DSAparams(const DSA *in, uint8_t **outp) {
+ CBB cbb;
+ if (!CBB_init(&cbb, 0) ||
+ !DSA_marshal_parameters(&cbb, in)) {
+ return -1;
+ }
+ return CBB_finish_i2d(&cbb, outp);
}
diff --git a/crypto/err/dsa.errordata b/crypto/err/dsa.errordata
index 3c5764a1..6f4bc138 100644
--- a/crypto/err/dsa.errordata
+++ b/crypto/err/dsa.errordata
@@ -1,4 +1,7 @@
DSA,100,BAD_Q_VALUE
+DSA,104,BAD_VERSION
+DSA,105,DECODE_ERROR
+DSA,106,ENCODE_ERROR
DSA,101,MISSING_PARAMETERS
DSA,102,MODULUS_TOO_LARGE
DSA,103,NEED_NEW_SETUP_VALUES