2016-08-23 19:38:07 +02:00
|
|
|
/*
|
2016-08-22 22:28:06 +02:00
|
|
|
* "This product includes software developed by the OpenSSL Project
|
|
|
|
* * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
|
|
|
*/
|
|
|
|
|
2015-12-17 14:09:44 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2016-08-22 22:26:23 +02:00
|
|
|
#include <civetweb.h>
|
|
|
|
#include <openssl/opensslconf.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2016-08-24 22:13:11 +02:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <sys/syslog.h>
|
2015-12-17 14:09:44 +01:00
|
|
|
#include <openssl/bio.h>
|
|
|
|
#include <openssl/err.h>
|
2016-08-28 14:16:50 +02:00
|
|
|
#include <openssl/ssl.h>
|
2015-12-17 14:09:44 +01:00
|
|
|
#include <openssl/pem.h>
|
|
|
|
#include <openssl/rand.h>
|
|
|
|
#include <openssl/ts.h>
|
|
|
|
#include <openssl/bn.h>
|
2016-08-26 20:39:45 +02:00
|
|
|
#include <syslog.h>
|
|
|
|
#include "utils.h"
|
2016-08-22 22:26:23 +02:00
|
|
|
|
2016-08-27 11:39:53 +02:00
|
|
|
#define OID_SECTION "oids"
|
2016-08-22 22:26:23 +02:00
|
|
|
|
|
|
|
/* Reply related functions. */
|
2016-08-24 22:13:11 +02:00
|
|
|
static int reply_command(CONF *conf, char *section, char *engine, char *query,
|
|
|
|
char *passin, char *inkey, const EVP_MD *md,
|
|
|
|
char *signer, char *chain, const char *policy,
|
|
|
|
char *in, int token_in, char *out, int token_out,
|
|
|
|
int text);
|
2016-08-22 22:26:23 +02:00
|
|
|
static TS_RESP *read_PKCS7(BIO *in_bio);
|
|
|
|
static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data);
|
|
|
|
static ASN1_INTEGER *next_serial(const char *serialfile);
|
|
|
|
static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
|
|
|
|
|
2016-08-23 19:38:07 +02:00
|
|
|
#define B_FORMAT_TEXT 0x8000
|
|
|
|
#define FORMAT_UNDEF 0
|
|
|
|
#define FORMAT_TEXT (1 | B_FORMAT_TEXT) /* Generic text */
|
|
|
|
#define FORMAT_ASN1 4 /* ASN.1/DER */
|
2015-12-17 14:09:44 +01:00
|
|
|
|
2016-08-22 22:26:23 +02:00
|
|
|
/*
|
|
|
|
* Reply-related method definitions.
|
|
|
|
*/
|
|
|
|
|
2016-08-29 08:34:59 +02:00
|
|
|
int add_oid_section(rfc3161_context *ct, CONF *conf) {
|
2016-08-27 11:39:53 +02:00
|
|
|
char *p;
|
2016-08-29 08:34:59 +02:00
|
|
|
STACK_OF(CONF_VALUE) * sktmp;
|
2016-08-27 11:39:53 +02:00
|
|
|
CONF_VALUE *cnf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if ((sktmp = NCONF_get_section(conf, OID_SECTION)) == NULL) {
|
|
|
|
uts_logger(ct, LOG_ERR, "problem loading oid section %s\n", p);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
|
|
|
|
cnf = sk_CONF_VALUE_value(sktmp, i);
|
|
|
|
if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
|
|
|
|
uts_logger(ct, LOG_ERR, "problem creating object %s=%s\n",
|
|
|
|
cnf->name, cnf->value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-08-29 08:34:59 +02:00
|
|
|
// static int reply_command(CONF *conf, char *section, char *engine, char
|
|
|
|
// *query,
|
|
|
|
// char *passin, char *inkey, const EVP_MD *md,
|
|
|
|
// char *signer, char *chain, const char *policy,
|
|
|
|
// char *in, int token_in, char *out, int token_out,
|
|
|
|
// int text) {
|
|
|
|
// int ret = 0;
|
|
|
|
// TS_RESP *response = NULL;
|
|
|
|
// BIO *in_bio = NULL;
|
|
|
|
// BIO *query_bio = NULL;
|
|
|
|
// BIO *inkey_bio = NULL;
|
|
|
|
// BIO *signer_bio = NULL;
|
|
|
|
// BIO *out_bio = NULL;
|
|
|
|
// BIO *bio_err;
|
|
|
|
//
|
|
|
|
// if (in != NULL) {
|
|
|
|
// if ((in_bio = BIO_new_file(in, "rb")) == NULL)
|
|
|
|
// goto end;
|
|
|
|
// if (token_in) {
|
|
|
|
// response = read_PKCS7(in_bio);
|
|
|
|
// } else {
|
|
|
|
// response = d2i_TS_RESP_bio(in_bio, NULL);
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// response = create_response(conf, section, engine, query, passin,
|
|
|
|
// inkey,
|
|
|
|
// md, signer, chain, policy);
|
|
|
|
// // if (response)
|
|
|
|
// // BIO_printf(bio_err, "Response has been
|
|
|
|
// // generated.\n");
|
|
|
|
// // else
|
|
|
|
// // BIO_printf(bio_err, "Response is not
|
|
|
|
// // generated.\n");
|
|
|
|
// }
|
|
|
|
// if (response == NULL)
|
|
|
|
// goto end;
|
|
|
|
//
|
|
|
|
// /* Write response. */
|
|
|
|
// if (text) {
|
|
|
|
// // if ((out_bio = bio_open_default(out, 'w', FORMAT_TEXT))
|
|
|
|
// //==
|
|
|
|
// // NULL)
|
|
|
|
// // goto end;
|
|
|
|
// if (token_out) {
|
|
|
|
// TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
|
|
|
|
// if (!TS_TST_INFO_print_bio(out_bio, tst_info))
|
|
|
|
// goto end;
|
|
|
|
// } else {
|
|
|
|
// if (!TS_RESP_print_bio(out_bio, response))
|
|
|
|
// goto end;
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// // if ((out_bio = bio_open_default(out, 'w', FORMAT_ASN1))
|
|
|
|
// //==
|
|
|
|
// // NULL)
|
|
|
|
// // goto end;
|
|
|
|
// if (token_out) {
|
|
|
|
// PKCS7 *token = TS_RESP_get_token(response);
|
|
|
|
// if (!i2d_PKCS7_bio(out_bio, token))
|
|
|
|
// goto end;
|
|
|
|
// } else {
|
|
|
|
// if (!i2d_TS_RESP_bio(out_bio, response))
|
|
|
|
// goto end;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// ret = 1;
|
|
|
|
//
|
|
|
|
// end:
|
|
|
|
// ERR_print_errors(bio_err);
|
|
|
|
// BIO_free_all(in_bio);
|
|
|
|
// BIO_free_all(query_bio);
|
|
|
|
// BIO_free_all(inkey_bio);
|
|
|
|
// BIO_free_all(signer_bio);
|
|
|
|
// BIO_free_all(out_bio);
|
|
|
|
// TS_RESP_free(response);
|
|
|
|
// return ret;
|
|
|
|
//}
|
2016-08-22 22:26:23 +02:00
|
|
|
|
|
|
|
/* Reads a PKCS7 token and adds default 'granted' status info to it. */
|
2016-08-23 19:38:07 +02:00
|
|
|
static TS_RESP *read_PKCS7(BIO *in_bio) {
|
|
|
|
int ret = 0;
|
|
|
|
PKCS7 *token = NULL;
|
|
|
|
TS_TST_INFO *tst_info = NULL;
|
|
|
|
TS_RESP *resp = NULL;
|
|
|
|
TS_STATUS_INFO *si = NULL;
|
|
|
|
|
|
|
|
if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
|
|
|
|
goto end;
|
|
|
|
if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL)
|
|
|
|
goto end;
|
|
|
|
if ((resp = TS_RESP_new()) == NULL)
|
|
|
|
goto end;
|
|
|
|
if ((si = TS_STATUS_INFO_new()) == NULL)
|
|
|
|
goto end;
|
|
|
|
// if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED))
|
|
|
|
// goto end;
|
|
|
|
if (!TS_RESP_set_status_info(resp, si))
|
|
|
|
goto end;
|
|
|
|
TS_RESP_set_tst_info(resp, token, tst_info);
|
|
|
|
token = NULL; /* Ownership is lost. */
|
|
|
|
tst_info = NULL; /* Ownership is lost. */
|
|
|
|
ret = 1;
|
2016-08-22 22:26:23 +02:00
|
|
|
|
|
|
|
end:
|
2016-08-23 19:38:07 +02:00
|
|
|
PKCS7_free(token);
|
|
|
|
TS_TST_INFO_free(tst_info);
|
|
|
|
if (!ret) {
|
|
|
|
TS_RESP_free(resp);
|
|
|
|
resp = NULL;
|
|
|
|
}
|
|
|
|
TS_STATUS_INFO_free(si);
|
|
|
|
return resp;
|
2016-08-22 22:26:23 +02:00
|
|
|
}
|
|
|
|
|
2016-08-26 20:39:45 +02:00
|
|
|
TS_RESP_CTX *create_tsctx(rfc3161_context *ct, CONF *conf, const char *section,
|
|
|
|
const char *policy) {
|
2016-08-27 00:24:22 +02:00
|
|
|
unsigned long err_code;
|
|
|
|
unsigned long err_code_prev = 0;
|
2016-08-26 01:28:34 +02:00
|
|
|
TS_RESP_CTX *resp_ctx = NULL;
|
2016-08-28 14:16:50 +02:00
|
|
|
|
|
|
|
SSL_load_error_strings();
|
|
|
|
ERR_load_BIO_strings();
|
|
|
|
SSL_library_init();
|
|
|
|
|
2016-08-26 20:39:45 +02:00
|
|
|
if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL) {
|
2016-08-26 21:00:40 +02:00
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"default_tsa", "tsa");
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 20:39:45 +02:00
|
|
|
}
|
2016-08-26 21:00:40 +02:00
|
|
|
if ((resp_ctx = TS_RESP_CTX_new()) == NULL) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to initialize tsa context");
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
2016-08-30 22:55:25 +02:00
|
|
|
TS_RESP_CTX_set_serial_cb(resp_ctx, serial_cb, NULL);
|
2016-08-26 21:00:40 +02:00
|
|
|
if (!TS_CONF_set_crypto_device(conf, section, NULL)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"crypto_device", section);
|
|
|
|
uts_logger(ct, LOG_ERR,
|
|
|
|
"failed to get or use the crypto device in section [ %s ]",
|
|
|
|
section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_signer_cert(conf, section, NULL, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"signer_cert", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_certs(conf, section, NULL, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"default_certs", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_signer_key(conf, section, NULL, NULL, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"signer_key", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
2016-08-26 01:28:34 +02:00
|
|
|
|
|
|
|
// if (md) {
|
|
|
|
// if (!TS_RESP_CTX_set_signer_digest(resp_ctx, md))
|
|
|
|
// goto end;
|
|
|
|
// } else if (!TS_CONF_set_signer_digest(conf, section, NULL, resp_ctx)) {
|
|
|
|
// goto end;
|
|
|
|
// }
|
|
|
|
|
2016-08-26 21:00:40 +02:00
|
|
|
if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"default_policy", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_policies(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"policies", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_digests(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"digests", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_accuracy(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"accuracy", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"clock_precision_digits", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_ordering(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"ordering", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_tsa_name(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"tsa_name", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
|
|
|
if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx)) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to get or use '%s' in section [ %s ]",
|
|
|
|
"ess_cert_id_chain", section);
|
2016-08-26 01:28:34 +02:00
|
|
|
goto end;
|
2016-08-26 21:00:40 +02:00
|
|
|
}
|
2016-08-28 14:23:42 +02:00
|
|
|
return resp_ctx;
|
2016-08-26 01:28:34 +02:00
|
|
|
end:
|
2016-08-27 00:24:22 +02:00
|
|
|
while ((err_code = ERR_get_error())) {
|
|
|
|
if (err_code_prev != err_code) {
|
|
|
|
ERR_load_TS_strings();
|
2016-08-27 01:04:19 +02:00
|
|
|
uts_logger(ct, LOG_DEBUG, "OpenSSL exception: '%s'",
|
2016-08-27 00:24:22 +02:00
|
|
|
ERR_error_string(err_code, NULL));
|
2016-08-27 11:39:53 +02:00
|
|
|
uts_logger(ct, LOG_ERR, "error '%s' in OpenSSL component '%s'",
|
2016-08-27 01:04:19 +02:00
|
|
|
ERR_reason_error_string(err_code),
|
|
|
|
ERR_lib_error_string(err_code));
|
2016-08-27 00:24:22 +02:00
|
|
|
}
|
|
|
|
err_code_prev = err_code;
|
|
|
|
}
|
2016-08-28 14:23:42 +02:00
|
|
|
TS_RESP_CTX_free(resp_ctx);
|
|
|
|
return NULL;
|
2016-08-26 01:28:34 +02:00
|
|
|
}
|
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
int create_response(rfc3161_context *ct, char *query, int query_len,
|
|
|
|
TS_RESP_CTX *resp_ctx, int *resp_size,
|
|
|
|
unsigned char **resp) {
|
2016-08-23 19:38:07 +02:00
|
|
|
int ret = 0;
|
2016-08-29 08:34:59 +02:00
|
|
|
TS_RESP *ts_response = NULL;
|
2016-08-23 19:38:07 +02:00
|
|
|
BIO *query_bio = NULL;
|
2016-08-29 08:34:59 +02:00
|
|
|
BIO *out_bio = NULL;
|
2016-08-30 22:55:25 +02:00
|
|
|
BIO *status_bio = BIO_new(BIO_s_mem());
|
|
|
|
;
|
|
|
|
unsigned long err_code;
|
|
|
|
unsigned long err_code_prev = 0;
|
2016-08-23 19:38:07 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
if ((query_bio = BIO_new_mem_buf(query, query_len)) == NULL) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to parse query");
|
2016-08-23 19:38:07 +02:00
|
|
|
goto end;
|
2016-08-30 22:55:25 +02:00
|
|
|
}
|
2016-08-29 08:34:59 +02:00
|
|
|
if ((ts_response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL) {
|
|
|
|
uts_logger(ct, LOG_ERR, "failed to create ts response");
|
2016-08-23 19:38:07 +02:00
|
|
|
goto end;
|
2016-08-29 08:34:59 +02:00
|
|
|
}
|
|
|
|
*resp_size = i2d_TS_RESP(ts_response, NULL);
|
|
|
|
*resp = calloc(*resp_size, sizeof(char));
|
|
|
|
|
|
|
|
i2d_TS_RESP(ts_response, resp);
|
2016-08-23 19:38:07 +02:00
|
|
|
ret = 1;
|
2016-08-22 22:26:23 +02:00
|
|
|
|
|
|
|
end:
|
2016-08-23 19:38:07 +02:00
|
|
|
if (!ret) {
|
2016-08-29 08:34:59 +02:00
|
|
|
TS_RESP_free(ts_response);
|
2016-08-23 19:38:07 +02:00
|
|
|
}
|
|
|
|
BIO_free_all(query_bio);
|
2016-08-30 22:55:25 +02:00
|
|
|
TS_STATUS_INFO_print_bio(status_bio, ts_response->status_info);
|
|
|
|
BUF_MEM *bptr;
|
|
|
|
BIO_get_mem_ptr(status_bio, &bptr);
|
|
|
|
|
|
|
|
// replacing '\n' by '|' to log on one line only
|
|
|
|
char *temp = strstr(bptr->data, "\n");
|
|
|
|
while ((temp = strstr(bptr->data, "\n")) != NULL) {
|
|
|
|
temp[0] = '|';
|
|
|
|
}
|
2016-08-22 22:26:23 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
long status = ASN1_INTEGER_get(ts_response->status_info->status);
|
|
|
|
switch (status) {
|
|
|
|
case TS_STATUS_GRANTED:
|
|
|
|
uts_logger(ct, LOG_INFO, "timestamp request granted");
|
|
|
|
break;
|
|
|
|
case TS_STATUS_GRANTED_WITH_MODS:
|
|
|
|
uts_logger(ct, LOG_NOTICE,
|
|
|
|
"timestamp request granted with modification");
|
|
|
|
break;
|
|
|
|
case TS_STATUS_REJECTION:
|
|
|
|
uts_logger(ct, LOG_WARNING, "timestamp request rejected");
|
|
|
|
break;
|
|
|
|
case TS_STATUS_WAITING:
|
|
|
|
uts_logger(ct, LOG_NOTICE, "timestamp request waiting");
|
|
|
|
break;
|
|
|
|
case TS_STATUS_REVOCATION_WARNING:
|
|
|
|
uts_logger(ct, LOG_WARNING, "timestamp request revocation warning");
|
|
|
|
break;
|
|
|
|
case TS_STATUS_REVOCATION_NOTIFICATION:
|
|
|
|
uts_logger(ct, LOG_NOTICE, "timestamp request revovation notification");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
uts_logger(ct, LOG_ERR, "unknown error code '%d'", status);
|
|
|
|
}
|
|
|
|
uts_logger(ct, LOG_DEBUG, "TimeStamp OpenSSL status: |%s", bptr->data);
|
2016-08-22 22:26:23 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
while ((err_code = ERR_get_error())) {
|
|
|
|
if (err_code_prev != err_code) {
|
|
|
|
ERR_load_TS_strings();
|
|
|
|
uts_logger(ct, LOG_DEBUG, "OpenSSL exception: '%s'",
|
|
|
|
ERR_error_string(err_code, NULL));
|
|
|
|
uts_logger(ct, LOG_ERR, "error '%s' in OpenSSL component '%s'",
|
|
|
|
ERR_reason_error_string(err_code),
|
|
|
|
ERR_lib_error_string(err_code));
|
|
|
|
}
|
|
|
|
err_code_prev = err_code;
|
|
|
|
}
|
|
|
|
// TS_TST_INFO_free(tst_info);
|
|
|
|
BIO_free(status_bio);
|
|
|
|
return ret;
|
2016-08-22 22:26:23 +02:00
|
|
|
}
|
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data42) {
|
|
|
|
unsigned char data[150] = {0};
|
|
|
|
RAND_bytes(data, sizeof(data));
|
|
|
|
// data[0] &= 0x7F;
|
2016-08-23 19:38:07 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
// build big number from our bytes
|
|
|
|
BIGNUM *bn = BN_new();
|
|
|
|
BN_bin2bn(data, sizeof(data), bn);
|
2016-08-23 19:38:07 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
// build the ASN1_INTEGER from our BIGNUM
|
|
|
|
ASN1_INTEGER *asnInt = ASN1_INTEGER_new();
|
|
|
|
BN_to_ASN1_INTEGER(bn, asnInt);
|
2016-08-22 22:26:23 +02:00
|
|
|
|
2016-08-30 22:55:25 +02:00
|
|
|
// cleanup
|
|
|
|
// ASN1_INTEGER_free(asnInt);
|
2016-08-23 19:38:07 +02:00
|
|
|
BN_free(bn);
|
2016-08-30 22:55:25 +02:00
|
|
|
return asnInt;
|
2015-12-18 00:29:43 +01:00
|
|
|
}
|