/*
- * Copyright (c) 2012, JANET(UK)
+ * Copyright (c) 2012, 2014, JANET(UK)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#include <openssl/dh.h>
+#include <trust_router/tr_dh.h>
+#include <openssl/bn.h>
+#include <openssl/sha.h>
+#include <talloc.h>
+#include <assert.h>
+#include <tid_internal.h>
+#include <tr_debug.h>
+
unsigned char tr_2048_dhprime[2048/8] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
-DH *tr_create_dh_params(char *priv_key,
+DH *tr_dh_new(void)
+{
+ return DH_new();
+}
+
+DH *tr_create_dh_params(unsigned char *priv_key,
size_t keylen) {
DH *dh = NULL;
(NULL == (dh->p = BN_new())) ||
(NULL == (dh->q = BN_new()))) {
DH_free(dh);
+ return NULL;
}
BN_set_word(dh->g, 2);
DH_check(dh, &dh_err);
if (0 != dh_err) {
- fprintf(stderr, "Warning: dh_check failed with %d", dh_err);
+ tr_warning("Warning: dh_check failed with %d", dh_err);
if (dh_err & DH_CHECK_P_NOT_PRIME)
- fprintf(stderr, ": p value is not prime\n");
+ tr_warning(": p value is not prime");
else if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
- fprintf(stderr, ": p value is not a safe prime\n");
+ tr_warning(": p value is not a safe prime");
else if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
- fprintf(stderr, ": unable to check the generator value\n");
+ tr_warning(": unable to check the generator value");
else if (dh_err & DH_NOT_SUITABLE_GENERATOR)
- fprintf (stderr, ": the g value is not a generator\n");
- else
- fprintf(stderr, "\n");
+ tr_warning(": the g value is not a generator");
+ else
+ tr_warning("unhandled error %i", dh_err);
}
-
+
return(dh);
}
-DH *tr_create_matching_dh (char *priv_key,
+DH *tr_create_matching_dh (unsigned char *priv_key,
size_t keylen,
DH *in_dh) {
DH *dh = NULL;
if (!in_dh)
return NULL;
- if (NULL == (dh = DH_new()))
+ if (NULL == (dh = DH_new())) {
+ tr_crit("tr_create_matching_dh: unable to allocate new DH structure.");
return NULL;
+ }
if ((NULL == (dh->g = BN_dup(in_dh->g))) ||
- (NULL == (dh->p = BN_dup(in_dh->p))) ||
- (NULL == (dh->q = BN_dup(in_dh->q)))) {
+ (NULL == (dh->p = BN_dup(in_dh->p)))) {
DH_free(dh);
+ tr_debug("tr_create_matching_dh: Invalid dh parameter values, can't be duped.");
+ return NULL;
}
/* TBD -- share code with previous function */
DH_generate_key(dh); /* generates the public key */
DH_check(dh, &dh_err);
if (0 != dh_err) {
- fprintf(stderr, "Warning: dh_check failed with %d", dh_err);
+ tr_warning("Warning: dh_check failed with %d", dh_err);
if (dh_err & DH_CHECK_P_NOT_PRIME)
- fprintf(stderr, ": p value is not prime\n");
+ tr_warning(": p value is not prime");
else if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
- fprintf(stderr, ": p value is not a safe prime\n");
+ tr_warning(": p value is not a safe prime");
else if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
- fprintf(stderr, ": unable to check the generator value\n");
+ tr_warning(": unable to check the generator value");
else if (dh_err & DH_NOT_SUITABLE_GENERATOR)
- fprintf (stderr, ": the g value is not a generator\n");
- else
- fprintf(stderr, "\n");
+ tr_warning(": the g value is not a generator");
+ else
+ tr_warning("unhandled error %i", dh_err);
}
-
+
return(dh);
}
}
}
-int tr_compute_dh_key(unsigned char *buf,
- size_t buflen,
- BIGNUM *pub_key,
- DH *priv_dh) {
+DH *tr_dh_dup(DH *in)
+{
+ DH *out=DH_new();
+
+ if (out==NULL)
+ return NULL;
+
+ if (in->g==NULL)
+ out->g=NULL;
+ else {
+ out->g=BN_dup(in->g);
+ if (out->g==NULL) {
+ DH_free(out);
+ return NULL;
+ }
+ }
+
+ if (in->p==NULL)
+ out->p=NULL;
+ else {
+ out->p=BN_dup(in->p);
+ if (out->p==NULL) {
+ DH_free(out);
+ return NULL;
+ }
+ }
+
+ if (in->q==NULL)
+ out->q=NULL;
+ else {
+ out->q=BN_dup(in->q);
+ if (out->q==NULL) {
+ DH_free(out);
+ return NULL;
+ }
+ }
+ if (in->priv_key==NULL)
+ out->priv_key=NULL;
+ else {
+ out->priv_key=BN_dup(in->priv_key);
+ if (out->priv_key==NULL) {
+ DH_free(out);
+ return NULL;
+ }
+ }
+
+ if (in->pub_key==NULL)
+ out->pub_key=NULL;
+ else {
+ out->pub_key=BN_dup(in->pub_key);
+ if (out->g==NULL) {
+ DH_free(out);
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
+int tr_compute_dh_key(unsigned char **pbuf,
+ BIGNUM *pub_key,
+ DH *priv_dh) {
+ size_t buflen;
+ unsigned char *buf = NULL;;
int rc = 0;
- if ((!buf) ||
- (!pub_key) ||
- (!priv_dh) ||
- (buflen < DH_size(priv_dh)))
+ if ((!pbuf) ||
+ (!pub_key) ||
+ (!priv_dh)) {
+ tr_debug("tr_compute_dh_key: Invalid parameters.");
return(-1);
+ }
+ *pbuf = NULL;
+ buflen = DH_size(priv_dh);
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ tr_crit("tr_compute_dh_key: out of memory");
+ return -1;
+ }
+
rc = DH_compute_key(buf, pub_key, priv_dh);
+ if (0 <= rc) {
+ *pbuf = buf;
+ }else {
+ free(buf);
+ }
return rc;
}
+int tr_dh_pub_hash(TID_REQ *request,
+ unsigned char **out_digest,
+ size_t *out_len)
+{
+ const BIGNUM *pub = request->tidc_dh->pub_key;
+ unsigned char *bn_bytes = talloc_zero_size(request, BN_num_bytes(pub));
+ unsigned char *digest = talloc_zero_size(request, SHA_DIGEST_LENGTH+1);
+ assert(bn_bytes && digest);
+ BN_bn2bin(pub, bn_bytes);
+ SHA1(bn_bytes, BN_num_bytes(pub), digest);
+ *out_digest = digest;
+ *out_len = SHA_DIGEST_LENGTH;
+
+ talloc_free(bn_bytes);
+ return 0;
+}
+
+void tr_dh_free(unsigned char *dh_buf)
+{
+ free(dh_buf);
+}
+
+void tr_dh_destroy(DH *dh)
+{
+ DH_free(dh);
+}