提交 2947af32 编写于 作者: B Beat Bolli 提交者: Matt Caswell

doc/man3: use the documented coding style in the example code

Adjust brace placement, whitespace after keywords, indentation and empty
lines after variable declarations according to
https://www.openssl.org/policies/codingstyle.html.

Indent literal sections by exactly one space.
Reviewed-by: NRich Salz <rsalz@openssl.org>
Reviewed-by: NMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1956)
上级 52df25cf
...@@ -100,14 +100,14 @@ Determine if one time is later or sooner than the current time: ...@@ -100,14 +100,14 @@ Determine if one time is later or sooner than the current time:
int day, sec; int day, sec;
if (!ASN1_TIME_diff(&day, &sec, NULL, to)) if (!ASN1_TIME_diff(&day, &sec, NULL, to))
/* Invalid time format */ /* Invalid time format */
if (day > 0 || sec > 0) if (day > 0 || sec > 0)
printf("Later\n"); printf("Later\n");
else if (day < 0 || sec < 0) else if (day < 0 || sec < 0)
printf("Sooner\n"); printf("Sooner\n");
else else
printf("Same\n"); printf("Same\n");
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -262,17 +262,17 @@ The following example demonstrates how to use most of the core async APIs: ...@@ -262,17 +262,17 @@ The following example demonstrates how to use most of the core async APIs:
} }
for (;;) { for (;;) {
switch(ASYNC_start_job(&job, ctx, &ret, jobfunc, msg, sizeof(msg))) { switch (ASYNC_start_job(&job, ctx, &ret, jobfunc, msg, sizeof(msg))) {
case ASYNC_ERR: case ASYNC_ERR:
case ASYNC_NO_JOBS: case ASYNC_NO_JOBS:
printf("An error occurred\n"); printf("An error occurred\n");
goto end; goto end;
case ASYNC_PAUSE: case ASYNC_PAUSE:
printf("Job was paused\n"); printf("Job was paused\n");
break; break;
case ASYNC_FINISH: case ASYNC_FINISH:
printf("Job finished with return value %d\n", ret); printf("Job finished with return value %d\n", ret);
goto end; goto end;
} }
/* Wait for the job to be woken */ /* Wait for the job to be woken */
......
...@@ -73,7 +73,7 @@ and not IPv4 addresses mapped to IPv6. ...@@ -73,7 +73,7 @@ and not IPv4 addresses mapped to IPv6.
These flags are bit flags, so they are to be combined with the These flags are bit flags, so they are to be combined with the
C<|> operator, for example: C<|> operator, for example:
BIO_connect(sock, addr, BIO_SOCK_KEEPALIVE | BIO_SOCK_NONBLOCK); BIO_connect(sock, addr, BIO_SOCK_KEEPALIVE | BIO_SOCK_NONBLOCK);
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -65,8 +65,8 @@ data to standard output: ...@@ -65,8 +65,8 @@ data to standard output:
bio = BIO_new_fp(stdin, BIO_NOCLOSE); bio = BIO_new_fp(stdin, BIO_NOCLOSE);
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_push(b64, bio); BIO_push(b64, bio);
while((inlen = BIO_read(b64, inbuf, 512)) > 0) while ((inlen = BIO_read(b64, inbuf, 512)) > 0)
BIO_write(bio_out, inbuf, inlen); BIO_write(bio_out, inbuf, inlen);
BIO_flush(bio_out); BIO_flush(bio_out);
BIO_free_all(b64); BIO_free_all(b64);
......
...@@ -82,7 +82,8 @@ checking has been omitted for clarity. ...@@ -82,7 +82,8 @@ checking has been omitted for clarity.
bio = BIO_new(BIO_s_null()); bio = BIO_new(BIO_s_null());
mdtmp = BIO_new(BIO_f_md()); mdtmp = BIO_new(BIO_f_md());
BIO_set_md(mdtmp, EVP_sha1()); BIO_set_md(mdtmp, EVP_sha1());
/* For BIO_push() we want to append the sink BIO and keep a note of /*
* For BIO_push() we want to append the sink BIO and keep a note of
* the start of the chain. * the start of the chain.
*/ */
bio = BIO_push(mdtmp, bio); bio = BIO_push(mdtmp, bio);
...@@ -105,8 +106,8 @@ The next example digests data by reading through a chain instead: ...@@ -105,8 +106,8 @@ The next example digests data by reading through a chain instead:
BIO_set_md(mdtmp, EVP_md5()); BIO_set_md(mdtmp, EVP_md5());
bio = BIO_push(mdtmp, bio); bio = BIO_push(mdtmp, bio);
do { do {
rdlen = BIO_read(bio, buf, sizeof(buf)); rdlen = BIO_read(bio, buf, sizeof(buf));
/* Might want to do something with the data here */ /* Might want to do something with the data here */
} while (rdlen > 0); } while (rdlen > 0);
This next example retrieves the message digests from a BIO chain and This next example retrieves the message digests from a BIO chain and
...@@ -118,15 +119,16 @@ outputs them. This could be used with the examples above. ...@@ -118,15 +119,16 @@ outputs them. This could be used with the examples above.
int i; int i;
mdtmp = bio; /* Assume bio has previously been set up */ mdtmp = bio; /* Assume bio has previously been set up */
do { do {
EVP_MD *md; EVP_MD *md;
mdtmp = BIO_find_type(mdtmp, BIO_TYPE_MD); mdtmp = BIO_find_type(mdtmp, BIO_TYPE_MD);
if (!mdtmp) break; if (!mdtmp)
BIO_get_md(mdtmp, &md); break;
printf("%s digest", OBJ_nid2sn(EVP_MD_type(md))); BIO_get_md(mdtmp, &md);
mdlen = BIO_gets(mdtmp, mdbuf, EVP_MAX_MD_SIZE); printf("%s digest", OBJ_nid2sn(EVP_MD_type(md)));
for (i = 0; i < mdlen; i++) printf(":%02X", mdbuf[i]); mdlen = BIO_gets(mdtmp, mdbuf, EVP_MAX_MD_SIZE);
printf("\n"); for (i = 0; i < mdlen; i++) printf(":%02X", mdbuf[i]);
mdtmp = BIO_next(mdtmp); printf("\n");
mdtmp = BIO_next(mdtmp);
} while (mdtmp); } while (mdtmp);
BIO_free_all(bio); BIO_free_all(bio);
......
...@@ -170,15 +170,15 @@ unencrypted example in L<BIO_s_connect(3)>. ...@@ -170,15 +170,15 @@ unencrypted example in L<BIO_s_connect(3)>.
exit(1); exit(1);
} }
if (BIO_do_handshake(sbio) <= 0) { if (BIO_do_handshake(sbio) <= 0) {
fprintf(stderr, "Error establishing SSL connection\n"); fprintf(stderr, "Error establishing SSL connection\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
exit(1); exit(1);
} }
/* XXX Could examine ssl here to get connection info */ /* XXX Could examine ssl here to get connection info */
BIO_puts(sbio, "GET / HTTP/1.0\n\n"); BIO_puts(sbio, "GET / HTTP/1.0\n\n");
for ( ; ; ) { for (;;) {
len = BIO_read(sbio, tmpbuf, 1024); len = BIO_read(sbio, tmpbuf, 1024);
if (len <= 0) if (len <= 0)
break; break;
...@@ -261,7 +261,7 @@ a client and also echoes the request to standard output. ...@@ -261,7 +261,7 @@ a client and also echoes the request to standard output.
BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n"); BIO_puts(sbio, "\r\nConnection Established\r\nRequest headers:\r\n");
BIO_puts(sbio, "--------------------------------------------------\r\n"); BIO_puts(sbio, "--------------------------------------------------\r\n");
for ( ; ; ) { for (;;) {
len = BIO_gets(sbio, tmpbuf, 1024); len = BIO_gets(sbio, tmpbuf, 1024);
if (len <= 0) if (len <= 0)
break; break;
......
...@@ -48,12 +48,13 @@ Traverse a chain looking for digest BIOs: ...@@ -48,12 +48,13 @@ Traverse a chain looking for digest BIOs:
btmp = in_bio; /* in_bio is chain to search through */ btmp = in_bio; /* in_bio is chain to search through */
do { do {
btmp = BIO_find_type(btmp, BIO_TYPE_MD); btmp = BIO_find_type(btmp, BIO_TYPE_MD);
if (btmp == NULL) break; /* Not found */ if (btmp == NULL)
/* btmp is a digest BIO, do something with it ...*/ break; /* Not found */
... /* btmp is a digest BIO, do something with it ...*/
...
btmp = BIO_next(btmp); btmp = BIO_next(btmp);
} while (btmp); } while (btmp);
......
...@@ -174,7 +174,7 @@ to retrieve a page and copy the result to standard output. ...@@ -174,7 +174,7 @@ to retrieve a page and copy the result to standard output.
exit(1); exit(1);
} }
BIO_puts(cbio, "GET / HTTP/1.0\n\n"); BIO_puts(cbio, "GET / HTTP/1.0\n\n");
for ( ; ; ) { for (;;) {
len = BIO_read(cbio, tmpbuf, 1024); len = BIO_read(cbio, tmpbuf, 1024);
if (len <= 0) if (len <= 0)
break; break;
......
...@@ -92,15 +92,18 @@ Alternative technique: ...@@ -92,15 +92,18 @@ Alternative technique:
BIO *bio_out; BIO *bio_out;
bio_out = BIO_new(BIO_s_file()); bio_out = BIO_new(BIO_s_file());
if (bio_out == NULL) /* Error ... */ if (bio_out == NULL)
if (!BIO_set_fp(bio_out, stdout, BIO_NOCLOSE)) /* Error ... */ /* Error */
if (!BIO_set_fp(bio_out, stdout, BIO_NOCLOSE))
/* Error */
BIO_printf(bio_out, "Hello World\n"); BIO_printf(bio_out, "Hello World\n");
Write to a file: Write to a file:
BIO *out; BIO *out;
out = BIO_new_file("filename.txt", "w"); out = BIO_new_file("filename.txt", "w");
if (!out) /* Error occurred */ if (!out)
/* Error */
BIO_printf(out, "Hello World\n"); BIO_printf(out, "Hello World\n");
BIO_free(out); BIO_free(out);
...@@ -108,8 +111,10 @@ Alternative technique: ...@@ -108,8 +111,10 @@ Alternative technique:
BIO *out; BIO *out;
out = BIO_new(BIO_s_file()); out = BIO_new(BIO_s_file());
if (out == NULL) /* Error ... */ if (out == NULL)
if (!BIO_write_filename(out, "filename.txt")) /* Error ... */ /* Error */
if (!BIO_write_filename(out, "filename.txt"))
/* Error */
BIO_printf(out, "Hello World\n"); BIO_printf(out, "Hello World\n");
BIO_free(out); BIO_free(out);
......
...@@ -122,7 +122,8 @@ or ...@@ -122,7 +122,8 @@ or
is called before the read and is called before the read and
callback_ex(b, BIO_CB_READ | BIO_CB_RETURN, data, dlen, 0, 0L, retvalue, readbytes) callback_ex(b, BIO_CB_READ | BIO_CB_RETURN, data, dlen, 0, 0L, retvalue,
readbytes)
or or
...@@ -140,7 +141,8 @@ or ...@@ -140,7 +141,8 @@ or
is called before the write and is called before the write and
callback_ex(b, BIO_CB_WRITE | BIO_CB_RETURN, data, dlen, 0, 0L, retvalue, written) callback_ex(b, BIO_CB_WRITE | BIO_CB_RETURN, data, dlen, 0, 0L, retvalue,
written)
or or
...@@ -158,7 +160,8 @@ or ...@@ -158,7 +160,8 @@ or
is called before the operation and is called before the operation and
callback_ex(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, 0, 0L, retvalue, readbytes) callback_ex(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size, 0, 0L, retvalue,
readbytes)
or or
......
...@@ -51,7 +51,8 @@ replace use of BN_CTX_init with BN_CTX_new instead: ...@@ -51,7 +51,8 @@ replace use of BN_CTX_init with BN_CTX_new instead:
BN_CTX *ctx; BN_CTX *ctx;
ctx = BN_CTX_new(); ctx = BN_CTX_new();
if(!ctx) /* Handle error */ if (!ctx)
/* error */
... ...
BN_CTX_free(ctx); BN_CTX_free(ctx);
......
...@@ -169,7 +169,8 @@ Instead applications should create a BN_GENCB structure using BN_GENCB_new: ...@@ -169,7 +169,8 @@ Instead applications should create a BN_GENCB structure using BN_GENCB_new:
BN_GENCB *callback; BN_GENCB *callback;
callback = BN_GENCB_new(); callback = BN_GENCB_new();
if(!callback) /* handle error */ if (!callback)
/* error */
... ...
BN_GENCB_free(callback); BN_GENCB_free(callback);
......
...@@ -65,9 +65,9 @@ Load a configuration file and print out any errors and exit (missing file ...@@ -65,9 +65,9 @@ Load a configuration file and print out any errors and exit (missing file
considered fatal): considered fatal):
if (CONF_modules_load_file(NULL, NULL, 0) <= 0) { if (CONF_modules_load_file(NULL, NULL, 0) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n"); fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
exit(1); exit(1);
} }
Load default configuration file using the section indicated by "myapp", Load default configuration file using the section indicated by "myapp",
...@@ -75,9 +75,9 @@ tolerate missing files, but exit on other errors: ...@@ -75,9 +75,9 @@ tolerate missing files, but exit on other errors:
if (CONF_modules_load_file(NULL, "myapp", if (CONF_modules_load_file(NULL, "myapp",
CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n"); fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
exit(1); exit(1);
} }
Load custom configuration file and section, only print warnings on error, Load custom configuration file and section, only print warnings on error,
...@@ -85,8 +85,8 @@ missing configuration file ignored: ...@@ -85,8 +85,8 @@ missing configuration file ignored:
if (CONF_modules_load_file("/something/app.cnf", "myapp", if (CONF_modules_load_file("/something/app.cnf", "myapp",
CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) { CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "WARNING: error loading configuration file\n"); fprintf(stderr, "WARNING: error loading configuration file\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
} }
Load and parse configuration file manually, custom error handling: Load and parse configuration file manually, custom error handling:
...@@ -96,22 +96,22 @@ Load and parse configuration file manually, custom error handling: ...@@ -96,22 +96,22 @@ Load and parse configuration file manually, custom error handling:
long eline; long eline;
fp = fopen("/somepath/app.cnf", "r"); fp = fopen("/somepath/app.cnf", "r");
if (fp == NULL) { if (fp == NULL) {
fprintf(stderr, "Error opening configuration file\n"); fprintf(stderr, "Error opening configuration file\n");
/* Other missing configuration file behaviour */ /* Other missing configuration file behaviour */
} else { } else {
cnf = NCONF_new(NULL); cnf = NCONF_new(NULL);
if (NCONF_load_fp(cnf, fp, &eline) == 0) { if (NCONF_load_fp(cnf, fp, &eline) == 0) {
fprintf(stderr, "Error on line %ld of configuration file\n", eline); fprintf(stderr, "Error on line %ld of configuration file\n", eline);
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
/* Other malformed configuration file behaviour */ /* Other malformed configuration file behaviour */
} else if (CONF_modules_load(cnf, "appname", 0) <= 0) { } else if (CONF_modules_load(cnf, "appname", 0) <= 0) {
fprintf(stderr, "Error configuring application\n"); fprintf(stderr, "Error configuring application\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
/* Other configuration error behaviour */ /* Other configuration error behaviour */
} }
fclose(fp); fclose(fp);
NCONF_free(cnf); NCONF_free(cnf);
} }
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -100,42 +100,42 @@ crypto.h where use of CRYPTO_THREAD_* types and functions is required. ...@@ -100,42 +100,42 @@ crypto.h where use of CRYPTO_THREAD_* types and functions is required.
This example safely initializes and uses a lock. This example safely initializes and uses a lock.
#ifdef _WIN32 #ifdef _WIN32
# include <windows.h> # include <windows.h>
#endif #endif
#include <openssl/crypto.h> #include <openssl/crypto.h>
static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT; static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT;
static CRYPTO_RWLOCK *lock; static CRYPTO_RWLOCK *lock;
static void myinit(void) static void myinit(void)
{ {
lock = CRYPTO_THREAD_lock_new(); lock = CRYPTO_THREAD_lock_new();
} }
static int mylock(void) static int mylock(void)
{ {
if (!CRYPTO_THREAD_run_once(&once, void init) || lock == NULL) if (!CRYPTO_THREAD_run_once(&once, void init) || lock == NULL)
return 0; return 0;
return CRYPTO_THREAD_write_lock(lock); return CRYPTO_THREAD_write_lock(lock);
} }
static int myunlock(void) static int myunlock(void)
{ {
return CRYPTO_THREAD_unlock(lock); return CRYPTO_THREAD_unlock(lock);
} }
int serialized(void) int serialized(void)
{ {
int ret = 0; int ret = 0;
if (mylock()) { if (mylock()) {
/* Your code here, do not return without releasing the lock! */ /* Your code here, do not return without releasing the lock! */
ret = ... ; ret = ... ;
} }
myunlock(); myunlock();
return ret; return ret;
} }
Finalization of locks is an advanced topic, not covered in this example. Finalization of locks is an advanced topic, not covered in this example.
This can only be done at process exit or when a dynamically loaded library is This can only be done at process exit or when a dynamically loaded library is
...@@ -149,9 +149,9 @@ You can find out if OpenSSL was configured with thread support: ...@@ -149,9 +149,9 @@ You can find out if OpenSSL was configured with thread support:
#include <openssl/opensslconf.h> #include <openssl/opensslconf.h>
#if defined(OPENSSL_THREADS) #if defined(OPENSSL_THREADS)
// thread support enabled // thread support enabled
#else #else
// no thread support // no thread support
#endif #endif
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -136,35 +136,31 @@ named curve prime256v1 (aka P-256). ...@@ -136,35 +136,31 @@ named curve prime256v1 (aka P-256).
First step: create an EC_KEY object (note: this part is B<not> ECDSA First step: create an EC_KEY object (note: this part is B<not> ECDSA
specific) specific)
int ret; int ret;
ECDSA_SIG *sig; ECDSA_SIG *sig;
EC_KEY *eckey; EC_KEY *eckey;
eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (eckey == NULL) { if (eckey == NULL)
/* error */ /* error */
} if (EC_KEY_generate_key(eckey) == 0)
if (EC_KEY_generate_key(eckey) == 0) { /* error */
/* error */
}
Second step: compute the ECDSA signature of a SHA-256 hash value Second step: compute the ECDSA signature of a SHA-256 hash value
using ECDSA_do_sign(): using ECDSA_do_sign():
sig = ECDSA_do_sign(digest, 32, eckey); sig = ECDSA_do_sign(digest, 32, eckey);
if (sig == NULL) { if (sig == NULL)
/* error */ /* error */
}
or using ECDSA_sign(): or using ECDSA_sign():
unsigned char *buffer, *pp; unsigned char *buffer, *pp;
int buf_len; int buf_len;
buf_len = ECDSA_size(eckey); buf_len = ECDSA_size(eckey);
buffer = OPENSSL_malloc(buf_len); buffer = OPENSSL_malloc(buf_len);
pp = buffer; pp = buffer;
if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0) { if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0)
/* error */ /* error */
}
Third step: verify the created ECDSA signature using ECDSA_do_verify(): Third step: verify the created ECDSA signature using ECDSA_do_verify():
...@@ -176,13 +172,12 @@ or using ECDSA_verify(): ...@@ -176,13 +172,12 @@ or using ECDSA_verify():
and finally evaluate the return value: and finally evaluate the return value:
if (ret == 1) { if (ret == 1)
/* signature ok */ /* signature ok */
} else if (ret == 0) { else if (ret == 0)
/* incorrect signature */ /* incorrect signature */
} else { else
/* error */ /* error */
}
=head1 CONFORMING TO =head1 CONFORMING TO
......
...@@ -385,17 +385,19 @@ illustrates how to approach this; ...@@ -385,17 +385,19 @@ illustrates how to approach this;
const char *engine_id = "ACME"; const char *engine_id = "ACME";
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
e = ENGINE_by_id(engine_id); e = ENGINE_by_id(engine_id);
if(!e) if (!e)
/* the engine isn't available */ /* the engine isn't available */
return; return;
if(!ENGINE_init(e)) { if (!ENGINE_init(e)) {
/* the engine couldn't initialise, release 'e' */ /* the engine couldn't initialise, release 'e' */
ENGINE_free(e); ENGINE_free(e);
return; return;
} }
if(!ENGINE_set_default_RSA(e)) if (!ENGINE_set_default_RSA(e))
/* This should only happen when 'e' can't initialise, but the previous /*
* statement suggests it did. */ * This should only happen when 'e' can't initialise, but the previous
* statement suggests it did.
*/
abort(); abort();
ENGINE_set_default_DSA(e); ENGINE_set_default_DSA(e);
ENGINE_set_default_ciphers(e); ENGINE_set_default_ciphers(e);
...@@ -474,9 +476,9 @@ boolean success or failure. ...@@ -474,9 +476,9 @@ boolean success or failure.
ENGINE *e = ENGINE_by_id(engine_id); ENGINE *e = ENGINE_by_id(engine_id);
if (!e) return 0; if (!e) return 0;
while (pre_num--) { while (pre_num--) {
if(!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) { if (!ENGINE_ctrl_cmd_string(e, pre_cmds[0], pre_cmds[1], 0)) {
fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id,
pre_cmds[0], pre_cmds[1] ? pre_cmds[1] : "(NULL)"); pre_cmds[0], pre_cmds[1] ? pre_cmds[1] : "(NULL)");
ENGINE_free(e); ENGINE_free(e);
return 0; return 0;
} }
...@@ -487,13 +489,15 @@ boolean success or failure. ...@@ -487,13 +489,15 @@ boolean success or failure.
ENGINE_free(e); ENGINE_free(e);
return 0; return 0;
} }
/* ENGINE_init() returned a functional reference, so free the structural /*
* reference from ENGINE_by_id(). */ * ENGINE_init() returned a functional reference, so free the structural
* reference from ENGINE_by_id().
*/
ENGINE_free(e); ENGINE_free(e);
while(post_num--) { while (post_num--) {
if(!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) { if (!ENGINE_ctrl_cmd_string(e, post_cmds[0], post_cmds[1], 0)) {
fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id, fprintf(stderr, "Failed command (%s - %s:%s)\n", engine_id,
post_cmds[0], post_cmds[1] ? post_cmds[1] : "(NULL)"); post_cmds[0], post_cmds[1] ? post_cmds[1] : "(NULL)");
ENGINE_finish(e); ENGINE_finish(e);
return 0; return 0;
} }
......
...@@ -23,8 +23,8 @@ B<str> is an array of error string data: ...@@ -23,8 +23,8 @@ B<str> is an array of error string data:
typedef struct ERR_string_data_st typedef struct ERR_string_data_st
{ {
unsigned long error; unsigned long error;
char *string; char *string;
} ERR_STRING_DATA; } ERR_STRING_DATA;
The error code is generated from the library number and a function and The error code is generated from the library number and a function and
......
...@@ -203,37 +203,37 @@ digest name passed on the command line. ...@@ -203,37 +203,37 @@ digest name passed on the command line.
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
EVP_MD_CTX *mdctx; EVP_MD_CTX *mdctx;
const EVP_MD *md; const EVP_MD *md;
char mess1[] = "Test Message\n"; char mess1[] = "Test Message\n";
char mess2[] = "Hello World\n"; char mess2[] = "Hello World\n";
unsigned char md_value[EVP_MAX_MD_SIZE]; unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len, i; int md_len, i;
if (argv[1] == NULL) { if (argv[1] == NULL) {
printf("Usage: mdtest digestname\n"); printf("Usage: mdtest digestname\n");
exit(1); exit(1);
} }
md = EVP_get_digestbyname(argv[1]); md = EVP_get_digestbyname(argv[1]);
if (md == NULL) { if (md == NULL) {
printf("Unknown message digest %s\n", argv[1]); printf("Unknown message digest %s\n", argv[1]);
exit(1); exit(1);
} }
mdctx = EVP_MD_CTX_new(); mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL); EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, mess1, strlen(mess1)); EVP_DigestUpdate(mdctx, mess1, strlen(mess1));
EVP_DigestUpdate(mdctx, mess2, strlen(mess2)); EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
EVP_DigestFinal_ex(mdctx, md_value, &md_len); EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx); EVP_MD_CTX_free(mdctx);
printf("Digest is: "); printf("Digest is: ");
for (i = 0; i < md_len; i++) for (i = 0; i < md_len; i++)
printf("%02x", md_value[i]); printf("%02x", md_value[i]);
printf("\n"); printf("\n");
exit(0); exit(0);
} }
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -540,101 +540,101 @@ for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode. ...@@ -540,101 +540,101 @@ for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode.
Encrypt a string using IDEA: Encrypt a string using IDEA:
int do_crypt(char *outfile) int do_crypt(char *outfile)
{ {
unsigned char outbuf[1024]; unsigned char outbuf[1024];
int outlen, tmplen; int outlen, tmplen;
/* Bogus key and IV: we'd normally set these from /*
* another source. * Bogus key and IV: we'd normally set these from
*/ * another source.
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; */
unsigned char iv[] = {1,2,3,4,5,6,7,8}; unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
char intext[] = "Some Crypto Text"; unsigned char iv[] = {1,2,3,4,5,6,7,8};
EVP_CIPHER_CTX *ctx; char intext[] = "Some Crypto Text";
FILE *out; EVP_CIPHER_CTX *ctx;
FILE *out;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv); ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv);
if(!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext)))
{ if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {
/* Error */ /* Error */
return 0; return 0;
} }
/* Buffer passed to EVP_EncryptFinal() must be after data just /*
* encrypted to avoid overwriting it. * Buffer passed to EVP_EncryptFinal() must be after data just
*/ * encrypted to avoid overwriting it.
if(!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) */
{ if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
/* Error */ /* Error */
return 0; return 0;
} }
outlen += tmplen; outlen += tmplen;
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
/* Need binary mode for fopen because encrypted data is /*
* binary data. Also cannot use strlen() on it because * Need binary mode for fopen because encrypted data is
* it won't be null terminated and may contain embedded * binary data. Also cannot use strlen() on it because
* nulls. * it won't be NUL terminated and may contain embedded
*/ * NULs.
out = fopen(outfile, "wb"); */
fwrite(outbuf, 1, outlen, out); out = fopen(outfile, "wb");
fclose(out); fwrite(outbuf, 1, outlen, out);
return 1; fclose(out);
} return 1;
}
The ciphertext from the above example can be decrypted using the B<openssl> The ciphertext from the above example can be decrypted using the B<openssl>
utility with the command line (shown on two lines for clarity): utility with the command line (shown on two lines for clarity):
openssl idea -d <filename openssl idea -d \
-K 000102030405060708090A0B0C0D0E0F -iv 0102030405060708 -K 000102030405060708090A0B0C0D0E0F -iv 0102030405060708 <filename
General encryption and decryption function example using FILE I/O and AES128 General encryption and decryption function example using FILE I/O and AES128
with a 128-bit key: with a 128-bit key:
int do_crypt(FILE *in, FILE *out, int do_encrypt) int do_crypt(FILE *in, FILE *out, int do_encrypt)
{ {
/* Allow enough space in output buffer for additional block */ /* Allow enough space in output buffer for additional block */
unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH]; unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen; int inlen, outlen;
EVP_CIPHER_CTX *ctx; EVP_CIPHER_CTX *ctx;
/* Bogus key and IV: we'd normally set these from /*
* another source. * Bogus key and IV: we'd normally set these from
*/ * another source.
unsigned char key[] = "0123456789abcdeF"; */
unsigned char iv[] = "1234567887654321"; unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "1234567887654321";
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new(); /* Don't set key or IV right away; we want to check lengths */
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL, ctx = EVP_CIPHER_CTX_new();
do_encrypt); EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16); do_encrypt);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16); OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);
/* Now we can set key and IV */
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt); /* Now we can set key and IV */
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);
for(;;)
{ for (;;) {
inlen = fread(inbuf, 1, 1024, in); inlen = fread(inbuf, 1, 1024, in);
if (inlen <= 0) break; if (inlen <= 0)
if(!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) break;
{ if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
/* Error */ /* Error */
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
return 0; return 0;
} }
fwrite(outbuf, 1, outlen, out); fwrite(outbuf, 1, outlen, out);
} }
if(!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) {
{ /* Error */
/* Error */ EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_CTX_free(ctx); return 0;
return 0; }
} fwrite(outbuf, 1, outlen, out);
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_free(ctx);
EVP_CIPHER_CTX_free(ctx); return 1;
return 1; }
}
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -132,17 +132,17 @@ salt value "salt" and info value "label": ...@@ -132,17 +132,17 @@ salt value "salt" and info value "label":
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
if (EVP_PKEY_derive_init(pctx) <= 0) if (EVP_PKEY_derive_init(pctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0) if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0) if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 6) <= 0) if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 6) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
/* Error */ /* Error */
=head1 CONFORMING TO =head1 CONFORMING TO
......
...@@ -80,15 +80,15 @@ and seed value "seed": ...@@ -80,15 +80,15 @@ and seed value "seed":
size_t outlen = sizeof(out); size_t outlen = sizeof(out);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL); pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
if (EVP_PKEY_derive_init(pctx) <= 0) if (EVP_PKEY_derive_init(pctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0) if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
/* Error */ /* Error */
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -52,28 +52,29 @@ Decrypt data using OAEP (for RSA keys): ...@@ -52,28 +52,29 @@ Decrypt data using OAEP (for RSA keys):
unsigned char *out, *in; unsigned char *out, *in;
size_t outlen, inlen; size_t outlen, inlen;
EVP_PKEY *key; EVP_PKEY *key;
/* NB: assumes key in, inlen are already set up /*
* NB: assumes key in, inlen are already set up
* and that key is an RSA private key * and that key is an RSA private key
*/ */
ctx = EVP_PKEY_CTX_new(key); ctx = EVP_PKEY_CTX_new(key);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_decrypt_init(ctx) <= 0) if (EVP_PKEY_decrypt_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0)
/* Error */ /* Error */
/* Determine buffer length */ /* Determine buffer length */
if (EVP_PKEY_decrypt(ctx, NULL, &outlen, in, inlen) <= 0) if (EVP_PKEY_decrypt(ctx, NULL, &outlen, in, inlen) <= 0)
/* Error */ /* Error */
out = OPENSSL_malloc(outlen); out = OPENSSL_malloc(outlen);
if (!out) if (!out)
/* malloc failure */ /* malloc failure */
if (EVP_PKEY_decrypt(ctx, out, &outlen, in, inlen) <= 0) if (EVP_PKEY_decrypt(ctx, out, &outlen, in, inlen) <= 0)
/* Error */ /* Error */
/* Decrypted data is outlen bytes written to buffer out */ /* Decrypted data is outlen bytes written to buffer out */
......
...@@ -57,23 +57,23 @@ Derive shared secret (for example DH or EC keys): ...@@ -57,23 +57,23 @@ Derive shared secret (for example DH or EC keys):
ctx = EVP_PKEY_CTX_new(pkey); ctx = EVP_PKEY_CTX_new(pkey);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_derive_init(ctx) <= 0) if (EVP_PKEY_derive_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_derive_set_peer(ctx, peerkey) <= 0) if (EVP_PKEY_derive_set_peer(ctx, peerkey) <= 0)
/* Error */ /* Error */
/* Determine buffer length */ /* Determine buffer length */
if (EVP_PKEY_derive(ctx, NULL, &skeylen) <= 0) if (EVP_PKEY_derive(ctx, NULL, &skeylen) <= 0)
/* Error */ /* Error */
skey = OPENSSL_malloc(skeylen); skey = OPENSSL_malloc(skeylen);
if (!skey) if (!skey)
/* malloc failure */ /* malloc failure */
if (EVP_PKEY_derive(ctx, skey, &skeylen) <= 0) if (EVP_PKEY_derive(ctx, skey, &skeylen) <= 0)
/* Error */ /* Error */
/* Shared secret is skey bytes written to buffer skey */ /* Shared secret is skey bytes written to buffer skey */
......
...@@ -56,28 +56,29 @@ set 'eng = NULL;' to start with the default OpenSSL RSA implementation: ...@@ -56,28 +56,29 @@ set 'eng = NULL;' to start with the default OpenSSL RSA implementation:
unsigned char *out, *in; unsigned char *out, *in;
size_t outlen, inlen; size_t outlen, inlen;
EVP_PKEY *key; EVP_PKEY *key;
/* NB: assumes eng, key, in, inlen are already set up, /*
* NB: assumes eng, key, in, inlen are already set up,
* and that key is an RSA public key * and that key is an RSA public key
*/ */
ctx = EVP_PKEY_CTX_new(key, eng); ctx = EVP_PKEY_CTX_new(key, eng);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_encrypt_init(ctx) <= 0) if (EVP_PKEY_encrypt_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_OAEP_PADDING) <= 0)
/* Error */ /* Error */
/* Determine buffer length */ /* Determine buffer length */
if (EVP_PKEY_encrypt(ctx, NULL, &outlen, in, inlen) <= 0) if (EVP_PKEY_encrypt(ctx, NULL, &outlen, in, inlen) <= 0)
/* Error */ /* Error */
out = OPENSSL_malloc(outlen); out = OPENSSL_malloc(outlen);
if (!out) if (!out)
/* malloc failure */ /* malloc failure */
if (EVP_PKEY_encrypt(ctx, out, &outlen, in, inlen) <= 0) if (EVP_PKEY_encrypt(ctx, out, &outlen, in, inlen) <= 0)
/* Error */ /* Error */
/* Encrypted data is outlen bytes written to buffer out */ /* Encrypted data is outlen bytes written to buffer out */
......
...@@ -100,15 +100,15 @@ Generate a 2048 bit RSA key: ...@@ -100,15 +100,15 @@ Generate a 2048 bit RSA key:
EVP_PKEY *pkey = NULL; EVP_PKEY *pkey = NULL;
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_keygen_init(ctx) <= 0) if (EVP_PKEY_keygen_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0) if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0)
/* Error */ /* Error */
/* Generate key */ /* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
/* Error */ /* Error */
Generate a key from a set of parameters: Generate a key from a set of parameters:
...@@ -120,13 +120,13 @@ Generate a key from a set of parameters: ...@@ -120,13 +120,13 @@ Generate a key from a set of parameters:
/* Assumed param is set up already */ /* Assumed param is set up already */
ctx = EVP_PKEY_CTX_new(param); ctx = EVP_PKEY_CTX_new(param);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_keygen_init(ctx) <= 0) if (EVP_PKEY_keygen_init(ctx) <= 0)
/* Error */ /* Error */
/* Generate key */ /* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0) if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
/* Error */ /* Error */
Example of generation callback for OpenSSL public key implementations: Example of generation callback for OpenSSL public key implementations:
...@@ -135,19 +135,22 @@ Example of generation callback for OpenSSL public key implementations: ...@@ -135,19 +135,22 @@ Example of generation callback for OpenSSL public key implementations:
EVP_PKEY_CTX_set_app_data(ctx, status_bio); EVP_PKEY_CTX_set_app_data(ctx, status_bio);
static int genpkey_cb(EVP_PKEY_CTX *ctx) static int genpkey_cb(EVP_PKEY_CTX *ctx)
{ {
char c = '*'; char c = '*';
BIO *b = EVP_PKEY_CTX_get_app_data(ctx); BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
int p; int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); if (p == 0)
if (p == 0) c = '.'; c = '.';
if (p == 1) c = '+'; if (p == 1)
if (p == 2) c = '*'; c = '+';
if (p == 3) c = '\n'; if (p == 2)
BIO_write(b, &c, 1); c = '*';
(void)BIO_flush(b); if (p == 3)
return 1; c = '\n';
} BIO_write(b, &c, 1);
(void)BIO_flush(b);
return 1;
}
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -66,25 +66,25 @@ Sign data using RSA with PKCS#1 padding and SHA256 digest: ...@@ -66,25 +66,25 @@ Sign data using RSA with PKCS#1 padding and SHA256 digest:
*/ */
ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */); ctx = EVP_PKEY_CTX_new(signing_key, NULL /* no engine */);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_sign_init(ctx) <= 0) if (EVP_PKEY_sign_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
/* Error */ /* Error */
/* Determine buffer length */ /* Determine buffer length */
if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0) if (EVP_PKEY_sign(ctx, NULL, &siglen, md, mdlen) <= 0)
/* Error */ /* Error */
sig = OPENSSL_malloc(siglen); sig = OPENSSL_malloc(siglen);
if (!sig) if (!sig)
/* malloc failure */ /* malloc failure */
if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0) if (EVP_PKEY_sign(ctx, sig, &siglen, md, mdlen) <= 0)
/* Error */ /* Error */
/* Signature is siglen bytes written to buffer sig */ /* Signature is siglen bytes written to buffer sig */
......
...@@ -55,23 +55,25 @@ Verify signature using PKCS#1 and SHA256 digest: ...@@ -55,23 +55,25 @@ Verify signature using PKCS#1 and SHA256 digest:
unsigned char *md, *sig; unsigned char *md, *sig;
size_t mdlen, siglen; size_t mdlen, siglen;
EVP_PKEY *verify_key; EVP_PKEY *verify_key;
/* NB: assumes verify_key, sig, siglen md and mdlen are already set up /*
* NB: assumes verify_key, sig, siglen md and mdlen are already set up
* and that verify_key is an RSA public key * and that verify_key is an RSA public key
*/ */
ctx = EVP_PKEY_CTX_new(verify_key); ctx = EVP_PKEY_CTX_new(verify_key);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_verify_init(ctx) <= 0) if (EVP_PKEY_verify_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
/* Error */ /* Error */
/* Perform operation */ /* Perform operation */
ret = EVP_PKEY_verify(ctx, sig, siglen, md, mdlen); ret = EVP_PKEY_verify(ctx, sig, siglen, md, mdlen);
/* ret == 1 indicates success, 0 verify failure and < 0 for some /*
* ret == 1 indicates success, 0 verify failure and < 0 for some
* other error. * other error.
*/ */
......
...@@ -60,30 +60,31 @@ Recover digest originally signed using PKCS#1 and SHA256 digest: ...@@ -60,30 +60,31 @@ Recover digest originally signed using PKCS#1 and SHA256 digest:
unsigned char *rout, *sig; unsigned char *rout, *sig;
size_t routlen, siglen; size_t routlen, siglen;
EVP_PKEY *verify_key; EVP_PKEY *verify_key;
/* NB: assumes verify_key, sig and siglen are already set up /*
* NB: assumes verify_key, sig and siglen are already set up
* and that verify_key is an RSA public key * and that verify_key is an RSA public key
*/ */
ctx = EVP_PKEY_CTX_new(verify_key); ctx = EVP_PKEY_CTX_new(verify_key);
if (!ctx) if (!ctx)
/* Error occurred */ /* Error occurred */
if (EVP_PKEY_verify_recover_init(ctx) <= 0) if (EVP_PKEY_verify_recover_init(ctx) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
/* Error */ /* Error */
if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0) if (EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()) <= 0)
/* Error */ /* Error */
/* Determine buffer length */ /* Determine buffer length */
if (EVP_PKEY_verify_recover(ctx, NULL, &routlen, sig, siglen) <= 0) if (EVP_PKEY_verify_recover(ctx, NULL, &routlen, sig, siglen) <= 0)
/* Error */ /* Error */
rout = OPENSSL_malloc(routlen); rout = OPENSSL_malloc(routlen);
if (!rout) if (!rout)
/* malloc failure */ /* malloc failure */
if (EVP_PKEY_verify_recover(ctx, rout, &routlen, sig, siglen) <= 0) if (EVP_PKEY_verify_recover(ctx, rout, &routlen, sig, siglen) <= 0)
/* Error */ /* Error */
/* Recovered data is routlen bytes written to buffer rout */ /* Recovered data is routlen bytes written to buffer rout */
......
...@@ -143,7 +143,7 @@ Create an object for B<commonName>: ...@@ -143,7 +143,7 @@ Create an object for B<commonName>:
Check if an object is B<commonName> Check if an object is B<commonName>
if (OBJ_obj2nid(obj) == NID_commonName) if (OBJ_obj2nid(obj) == NID_commonName)
/* Do something */ /* Do something */
Create a new NID and initialize an object from it: Create a new NID and initialize an object from it:
......
...@@ -93,7 +93,7 @@ B<issuer>: ...@@ -93,7 +93,7 @@ B<issuer>:
if (OCSP_REQUEST_add0_id(req, cid) == NULL) if (OCSP_REQUEST_add0_id(req, cid) == NULL)
/* error */ /* error */
/* Do something with req, e.g. query responder */ /* Do something with req, e.g. query responder */
OCSP_REQUEST_free(req); OCSP_REQUEST_free(req);
......
...@@ -306,43 +306,38 @@ Read a certificate in PEM format from a BIO: ...@@ -306,43 +306,38 @@ Read a certificate in PEM format from a BIO:
X509 *x; X509 *x;
x = PEM_read_bio_X509(bp, NULL, 0, NULL); x = PEM_read_bio_X509(bp, NULL, 0, NULL);
if (x == NULL) { if (x == NULL)
/* Error */ /* Error */
}
Alternative method: Alternative method:
X509 *x = NULL; X509 *x = NULL;
if (!PEM_read_bio_X509(bp, &x, 0, NULL)) { if (!PEM_read_bio_X509(bp, &x, 0, NULL))
/* Error */ /* Error */
}
Write a certificate to a BIO: Write a certificate to a BIO:
if (!PEM_write_bio_X509(bp, x)) { if (!PEM_write_bio_X509(bp, x))
/* Error */ /* Error */
}
Write a private key (using traditional format) to a BIO using Write a private key (using traditional format) to a BIO using
triple DES encryption, the pass phrase is prompted for: triple DES encryption, the pass phrase is prompted for:
if (!PEM_write_bio_PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, NULL)) { if (!PEM_write_bio_PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, NULL))
/* Error */ /* Error */
}
Write a private key (using PKCS#8 format) to a BIO using triple Write a private key (using PKCS#8 format) to a BIO using triple
DES encryption, using the pass phrase "hello": DES encryption, using the pass phrase "hello":
if (!PEM_write_bio_PKCS8PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, "hello")) { if (!PEM_write_bio_PKCS8PrivateKey(bp, key, EVP_des_ede3_cbc(),
NULL, 0, 0, "hello"))
/* Error */ /* Error */
}
Read a private key from a BIO using a pass phrase callback: Read a private key from a BIO using a pass phrase callback:
key = PEM_read_bio_PrivateKey(bp, NULL, pass_cb, "My Private Key"); key = PEM_read_bio_PrivateKey(bp, NULL, pass_cb, "My Private Key");
if (key == NULL) { if (key == NULL)
/* Error */ /* Error */
}
Skeleton pass phrase callback: Skeleton pass phrase callback:
...@@ -432,9 +427,8 @@ The pseudo code to derive the key would look similar to: ...@@ -432,9 +427,8 @@ The pseudo code to derive the key would look similar to:
memcpy(iv, HexToBin("3F17F5316E2BAC89"), niv); memcpy(iv, HexToBin("3F17F5316E2BAC89"), niv);
rc = EVP_BytesToKey(cipher, md, iv /*salt*/, pword, plen, 1, key, NULL /*iv*/); rc = EVP_BytesToKey(cipher, md, iv /*salt*/, pword, plen, 1, key, NULL /*iv*/);
if (rc != nkey) { if (rc != nkey)
/* Error */ /* Error */
}
/* On success, use key and iv to initialize the cipher */ /* On success, use key and iv to initialize the cipher */
......
...@@ -47,38 +47,38 @@ the result to a new file. ...@@ -47,38 +47,38 @@ the result to a new file.
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
FILE *fp; FILE *fp;
PKCS12 *p12; PKCS12 *p12;
if (argc != 5) { if (argc != 5) {
fprintf(stderr, "Usage: pkread p12file password newpass opfile\n"); fprintf(stderr, "Usage: pkread p12file password newpass opfile\n");
return 1; return 1;
} }
if ((fp = fopen(argv[1], "rb")) == NULL) { if ((fp = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "Error opening file %s\n", argv[1]); fprintf(stderr, "Error opening file %s\n", argv[1]);
return 1; return 1;
} }
p12 = d2i_PKCS12_fp(fp, NULL); p12 = d2i_PKCS12_fp(fp, NULL);
fclose(fp); fclose(fp);
if (p12 == NULL) { if (p12 == NULL) {
fprintf(stderr, "Error reading PKCS#12 file\n"); fprintf(stderr, "Error reading PKCS#12 file\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
return 1; return 1;
} }
if (PKCS12_newpass(p12, argv[2], argv[3]) == 0) { if (PKCS12_newpass(p12, argv[2], argv[3]) == 0) {
fprintf(stderr, "Error changing password\n"); fprintf(stderr, "Error changing password\n");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
PKCS12_free(p12); PKCS12_free(p12);
return 1; return 1;
} }
if ((fp = fopen(argv[4], "wb")) == NULL) { if ((fp = fopen(argv[4], "wb")) == NULL) {
fprintf(stderr, "Error opening file %s\n", argv[4]); fprintf(stderr, "Error opening file %s\n", argv[4]);
PKCS12_free(p12); PKCS12_free(p12);
return 1; return 1;
} }
i2d_PKCS12_fp(fp, p12); i2d_PKCS12_fp(fp, p12);
PKCS12_free(p12); PKCS12_free(p12);
fclose(fp); fclose(fp);
return 0; return 0;
} }
......
...@@ -37,12 +37,12 @@ API is being used, so this function is no longer recommended. ...@@ -37,12 +37,12 @@ API is being used, so this function is no longer recommended.
typedef struct rand_meth_st typedef struct rand_meth_st
{ {
void (*seed)(const void *buf, int num); void (*seed)(const void *buf, int num);
int (*bytes)(unsigned char *buf, int num); int (*bytes)(unsigned char *buf, int num);
void (*cleanup)(void); void (*cleanup)(void);
void (*add)(const void *buf, int num, int entropy); void (*add)(const void *buf, int num, int entropy);
int (*pseudorand)(unsigned char *buf, int num); int (*pseudorand)(unsigned char *buf, int num);
int (*status)(void); int (*status)(void);
} RAND_METHOD; } RAND_METHOD;
The components point to method implementations used by (or called by), in order, The components point to method implementations used by (or called by), in order,
......
...@@ -81,56 +81,56 @@ the default method is used. ...@@ -81,56 +81,56 @@ the default method is used.
typedef struct rsa_meth_st typedef struct rsa_meth_st
{ {
/* name of the implementation */ /* name of the implementation */
const char *name; const char *name;
/* encrypt */ /* encrypt */
int (*rsa_pub_enc)(int flen, unsigned char *from, int (*rsa_pub_enc)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding); unsigned char *to, RSA *rsa, int padding);
/* verify arbitrary data */ /* verify arbitrary data */
int (*rsa_pub_dec)(int flen, unsigned char *from, int (*rsa_pub_dec)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding); unsigned char *to, RSA *rsa, int padding);
/* sign arbitrary data */ /* sign arbitrary data */
int (*rsa_priv_enc)(int flen, unsigned char *from, int (*rsa_priv_enc)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding); unsigned char *to, RSA *rsa, int padding);
/* decrypt */ /* decrypt */
int (*rsa_priv_dec)(int flen, unsigned char *from, int (*rsa_priv_dec)(int flen, unsigned char *from,
unsigned char *to, RSA *rsa, int padding); unsigned char *to, RSA *rsa, int padding);
/* compute r0 = r0 ^ I mod rsa->n (May be NULL for some /* compute r0 = r0 ^ I mod rsa->n (May be NULL for some implementations) */
implementations) */ int (*rsa_mod_exp)(BIGNUM *r0, BIGNUM *I, RSA *rsa);
int (*rsa_mod_exp)(BIGNUM *r0, BIGNUM *I, RSA *rsa);
/* compute r = a ^ p mod m (May be NULL for some implementations) */ /* compute r = a ^ p mod m (May be NULL for some implementations) */
int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p, int (*bn_mod_exp)(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
/* called at RSA_new */ /* called at RSA_new */
int (*init)(RSA *rsa); int (*init)(RSA *rsa);
/* called at RSA_free */ /* called at RSA_free */
int (*finish)(RSA *rsa); int (*finish)(RSA *rsa);
/* RSA_FLAG_EXT_PKEY - rsa_mod_exp is called for private key /*
* RSA_FLAG_EXT_PKEY - rsa_mod_exp is called for private key
* operations, even if p,q,dmp1,dmq1,iqmp * operations, even if p,q,dmp1,dmq1,iqmp
* are NULL * are NULL
* RSA_METHOD_FLAG_NO_CHECK - don't check pub/private match * RSA_METHOD_FLAG_NO_CHECK - don't check pub/private match
*/ */
int flags; int flags;
char *app_data; /* ?? */ char *app_data; /* ?? */
int (*rsa_sign)(int type, int (*rsa_sign)(int type,
const unsigned char *m, unsigned int m_length, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa); unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
int (*rsa_verify)(int dtype, int (*rsa_verify)(int dtype,
const unsigned char *m, unsigned int m_length, const unsigned char *m, unsigned int m_length,
const unsigned char *sigbuf, unsigned int siglen, const unsigned char *sigbuf, unsigned int siglen,
const RSA *rsa); const RSA *rsa);
/* keygen. If NULL builtin RSA key generation will be used */ /* keygen. If NULL builtin RSA key generation will be used */
int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
} RSA_METHOD; } RSA_METHOD;
......
...@@ -18,21 +18,21 @@ SCT_get_source, SCT_set_source ...@@ -18,21 +18,21 @@ SCT_get_source, SCT_set_source
#include <openssl/ct.h> #include <openssl/ct.h>
typedef enum { typedef enum {
CT_LOG_ENTRY_TYPE_NOT_SET = -1, CT_LOG_ENTRY_TYPE_NOT_SET = -1,
CT_LOG_ENTRY_TYPE_X509 = 0, CT_LOG_ENTRY_TYPE_X509 = 0,
CT_LOG_ENTRY_TYPE_PRECERT = 1 CT_LOG_ENTRY_TYPE_PRECERT = 1
} ct_log_entry_type_t; } ct_log_entry_type_t;
typedef enum { typedef enum {
SCT_VERSION_NOT_SET = -1, SCT_VERSION_NOT_SET = -1,
SCT_VERSION_V1 = 0 SCT_VERSION_V1 = 0
} sct_version_t; } sct_version_t;
typedef enum { typedef enum {
SCT_SOURCE_UNKNOWN, SCT_SOURCE_UNKNOWN,
SCT_SOURCE_TLS_EXTENSION, SCT_SOURCE_TLS_EXTENSION,
SCT_SOURCE_X509V3_EXTENSION, SCT_SOURCE_X509V3_EXTENSION,
SCT_SOURCE_OCSP_STAPLED_RESPONSE SCT_SOURCE_OCSP_STAPLED_RESPONSE
} sct_source_t; } sct_source_t;
SCT *SCT_new(void); SCT *SCT_new(void);
......
...@@ -10,12 +10,12 @@ checks Signed Certificate Timestamps (SCTs) are valid ...@@ -10,12 +10,12 @@ checks Signed Certificate Timestamps (SCTs) are valid
#include <openssl/ct.h> #include <openssl/ct.h>
typedef enum { typedef enum {
SCT_VALIDATION_STATUS_NOT_SET, SCT_VALIDATION_STATUS_NOT_SET,
SCT_VALIDATION_STATUS_UNKNOWN_LOG, SCT_VALIDATION_STATUS_UNKNOWN_LOG,
SCT_VALIDATION_STATUS_VALID, SCT_VALIDATION_STATUS_VALID,
SCT_VALIDATION_STATUS_INVALID, SCT_VALIDATION_STATUS_INVALID,
SCT_VALIDATION_STATUS_UNVERIFIED, SCT_VALIDATION_STATUS_UNVERIFIED,
SCT_VALIDATION_STATUS_UNKNOWN_VERSION SCT_VALIDATION_STATUS_UNKNOWN_VERSION
} sct_validation_status_t; } sct_validation_status_t;
int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx); int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx);
......
...@@ -41,15 +41,12 @@ If the file "config.cnf" contains the following: ...@@ -41,15 +41,12 @@ If the file "config.cnf" contains the following:
[test_sect] [test_sect]
# list of confuration modules # list of confuration modules
ssl_conf = ssl_sect ssl_conf = ssl_sect
[ssl_sect] [ssl_sect]
server = server_section server = server_section
[server_section] [server_section]
RSA.Certificate = server-rsa.pem RSA.Certificate = server-rsa.pem
ECDSA.Certificate = server-ecdsa.pem ECDSA.Certificate = server-ecdsa.pem
Ciphers = ALL:!RC4 Ciphers = ALL:!RC4
...@@ -57,8 +54,8 @@ If the file "config.cnf" contains the following: ...@@ -57,8 +54,8 @@ If the file "config.cnf" contains the following:
An application could call: An application could call:
if (CONF_modules_load_file("config.cnf", "testapp", 0) <= 0) { if (CONF_modules_load_file("config.cnf", "testapp", 0) <= 0) {
fprintf(stderr, "Error processing config file\n"); fprintf(stderr, "Error processing config file\n");
goto err; goto err;
} }
ctx = SSL_CTX_new(TLS_server_method()); ctx = SSL_CTX_new(TLS_server_method());
......
...@@ -190,139 +190,137 @@ The actual name matched in the certificate (which might be a wildcard) is ...@@ -190,139 +190,137 @@ The actual name matched in the certificate (which might be a wildcard) is
retrieved, and must be copied by the application if it is to be retained beyond retrieved, and must be copied by the application if it is to be retained beyond
the lifetime of the SSL connection. the lifetime of the SSL connection.
SSL_CTX *ctx; SSL_CTX *ctx;
SSL *ssl; SSL *ssl;
int (*verify_cb)(int ok, X509_STORE_CTX *sctx) = NULL; int (*verify_cb)(int ok, X509_STORE_CTX *sctx) = NULL;
int num_usable = 0; int num_usable = 0;
const char *nexthop_domain = "example.com"; const char *nexthop_domain = "example.com";
const char *dane_tlsa_domain = "smtp.example.com"; const char *dane_tlsa_domain = "smtp.example.com";
uint8_t usage, selector, mtype; uint8_t usage, selector, mtype;
if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL) if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL)
/* handle error */ /* error */
if (SSL_CTX_dane_enable(ctx) <= 0) if (SSL_CTX_dane_enable(ctx) <= 0)
/* handle error */ /* error */
if ((ssl = SSL_new(ctx)) == NULL)
if ((ssl = SSL_new(ctx)) == NULL) /* error */
/* handle error */ if (SSL_dane_enable(ssl, dane_tlsa_domain) <= 0)
/* error */
if (SSL_dane_enable(ssl, dane_tlsa_domain) <= 0)
/* handle error */ /*
* For many applications it is safe to skip DANE-EE(3) namechecks. Do not
/* * disable the checks unless "unknown key share" attacks pose no risk for
* For many applications it is safe to skip DANE-EE(3) namechecks. Do not * your application.
* disable the checks unless "unknown key share" attacks pose no risk for */
* your application. SSL_dane_set_flags(ssl, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
*/
SSL_dane_set_flags(ssl, DANE_FLAG_NO_DANE_EE_NAMECHECKS); if (!SSL_add1_host(ssl, nexthop_domain))
/* error */
if (!SSL_add1_host(ssl, nexthop_domain)) SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
/* handle error */
SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); for (... each TLSA record ...) {
unsigned char *data;
for (... each TLSA record ...) { size_t len;
unsigned char *data; int ret;
size_t len;
int ret; /* set usage, selector, mtype, data, len */
/* set usage, selector, mtype, data, len */ /*
* Opportunistic DANE TLS clients support only DANE-TA(2) or DANE-EE(3).
/* * They treat all other certificate usages, and in particular PKIX-TA(0)
* Opportunistic DANE TLS clients support only DANE-TA(2) or DANE-EE(3). * and PKIX-EE(1), as unusable.
* They treat all other certificate usages, and in particular PKIX-TA(0) */
* and PKIX-EE(1), as unusable. switch (usage) {
*/ default:
switch (usage) { case 0: /* PKIX-TA(0) */
default: case 1: /* PKIX-EE(1) */
case 0: /* PKIX-TA(0) */ continue;
case 1: /* PKIX-EE(1) */ case 2: /* DANE-TA(2) */
continue; case 3: /* DANE-EE(3) */
case 2: /* DANE-TA(2) */ break;
case 3: /* DANE-EE(3) */ }
break;
} ret = SSL_dane_tlsa_add(ssl, usage, selector, mtype, data, len);
/* free data as appropriate */
ret = SSL_dane_tlsa_add(ssl, usage, selector, mtype, data, len);
/* free data as appropriate */ if (ret < 0)
/* handle SSL library internal error */
if (ret < 0) else if (ret == 0)
/* handle SSL library internal error */ /* handle unusable TLSA record */
else if (ret == 0) else
/* handle unusable TLSA record */ ++num_usable;
else }
++num_usable;
} /*
* At this point, the verification mode is still the default SSL_VERIFY_NONE.
/* * Opportunistic DANE clients use unauthenticated TLS when all TLSA records
* At this point, the verification mode is still the default SSL_VERIFY_NONE. * are unusable, so continue the handshake even if authentication fails.
* Opportunistic DANE clients use unauthenticated TLS when all TLSA records */
* are unusable, so continue the handshake even if authentication fails. if (num_usable == 0) {
*/ /* Log all records unusable? */
if (num_usable == 0) {
/* Log all records unusable? */ /* Optionally set verify_cb to a suitable non-NULL callback. */
SSL_set_verify(ssl, SSL_VERIFY_NONE, verify_cb);
/* Optionally set verify_cb to a suitable non-NULL callback. */ } else {
SSL_set_verify(ssl, SSL_VERIFY_NONE, verify_cb); /* At least one usable record. We expect to verify the peer */
} else {
/* At least one usable record. We expect to verify the peer */ /* Optionally set verify_cb to a suitable non-NULL callback. */
/* Optionally set verify_cb to a suitable non-NULL callback. */ /*
* Below we elect to fail the handshake when peer verification fails.
/* * Alternatively, use the permissive SSL_VERIFY_NONE verification mode,
* Below we elect to fail the handshake when peer verification fails. * complete the handshake, check the verification status, and if not
* Alternatively, use the permissive SSL_VERIFY_NONE verification mode, * verified disconnect gracefully at the application layer, especially if
* complete the handshake, check the verification status, and if not * application protocol supports informing the server that authentication
* verified disconnect gracefully at the application layer, especially if * failed.
* application protocol supports informing the server that authentication */
* failed. SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_cb);
*/ }
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_cb);
} /*
* Load any saved session for resumption, making sure that the previous
/* * session applied the same security and authentication requirements that
* Load any saved session for resumption, making sure that the previous * would be expected of a fresh connection.
* session applied the same security and authentication requirements that */
* would be expected of a fresh connection.
*/ /* Perform SSL_connect() handshake and handle errors here */
/* Perform SSL_connect() handshake and handle errors here */ if (SSL_session_reused(ssl)) {
if (SSL_get_verify_result(ssl) == X509_V_OK) {
if (SSL_session_reused(ssl)) { /*
if (SSL_get_verify_result(ssl) == X509_V_OK) { * Resumed session was originally verified, this connection is
/* * authenticated.
* Resumed session was originally verified, this connection is */
* authenticated. } else {
*/ /*
} else { * Resumed session was not originally verified, this connection is not
/* * authenticated.
* Resumed session was not originally verified, this connection is not */
* authenticated. }
*/ } else if (SSL_get_verify_result(ssl) == X509_V_OK) {
} const char *peername = SSL_get0_peername(ssl);
} else if (SSL_get_verify_result(ssl) == X509_V_OK) { EVP_PKEY *mspki = NULL;
const char *peername = SSL_get0_peername(ssl);
EVP_PKEY *mspki = NULL; int depth = SSL_get0_dane_authority(ssl, NULL, &mspki);
if (depth >= 0) {
int depth = SSL_get0_dane_authority(ssl, NULL, &mspki); (void) SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, NULL, NULL);
if (depth >= 0) { printf("DANE TLSA %d %d %d %s at depth %d\n", usage, selector, mtype,
(void) SSL_get0_dane_tlsa(ssl, &usage, &selector, &mtype, NULL, NULL); (mspki != NULL) ? "TA public key verified certificate" :
printf("DANE TLSA %d %d %d %s at depth %d\n", usage, selector, mtype, depth ? "matched TA certificate" : "matched EE certificate",
(mspki != NULL) ? "TA public key verified certificate" : depth);
depth ? "matched TA certificate" : "matched EE certificate", }
depth); if (peername != NULL) {
} /* Name checks were in scope and matched the peername */
if (peername != NULL) { printf("Verified peername: %s\n", peername);
/* Name checks were in scope and matched the peername */ }
printf("Verified peername: %s\n", peername); } else {
} /*
} else { * Not authenticated, presumably all TLSA rrs unusable, but possibly a
/* * callback suppressed connection termination despite the presence of
* Not authenticated, presumably all TLSA rrs unusable, but possibly a * usable TLSA RRs none of which matched. Do whatever is appropriate for
* callback suppressed connection termination despite the presence of * fresh unauthenticated connections.
* usable TLSA RRs none of which matched. Do whatever is appropriate for */
* fresh unauthenticated connections. }
*/
}
=head1 NOTES =head1 NOTES
......
...@@ -108,7 +108,7 @@ ca1.pem ca2.pem ca3.pem: ...@@ -108,7 +108,7 @@ ca1.pem ca2.pem ca3.pem:
#!/bin/sh #!/bin/sh
rm CAfile.pem rm CAfile.pem
for i in ca1.pem ca2.pem ca3.pem ; do for i in ca1.pem ca2.pem ca3.pem ; do
openssl x509 -in $i -text >> CAfile.pem openssl x509 -in $i -text >> CAfile.pem
done done
Prepare the directory /some/where/certs containing several CA certificates Prepare the directory /some/where/certs containing several CA certificates
......
...@@ -86,14 +86,14 @@ The use of MD5 as a digest is strongly discouraged due to security weaknesses. ...@@ -86,14 +86,14 @@ The use of MD5 as a digest is strongly discouraged due to security weaknesses.
Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA
using an array: using an array:
const int slist[] = {NID_sha256, EVP_PKEY_EC, NID_sha256, EVP_PKEY_RSA}; const int slist[] = {NID_sha256, EVP_PKEY_EC, NID_sha256, EVP_PKEY_RSA};
SSL_CTX_set1_sigalgs(ctx, slist, 4); SSL_CTX_set1_sigalgs(ctx, slist, 4);
Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA
using a string: using a string:
SSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256:RSA+SHA256"); SSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256:RSA+SHA256");
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -82,7 +82,7 @@ The operation succeeded. ...@@ -82,7 +82,7 @@ The operation succeeded.
Scan all certificates in B<CAfile> and list them as acceptable CAs: Scan all certificates in B<CAfile> and list them as acceptable CAs:
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile)); SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(CAfile));
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -85,9 +85,9 @@ truncated. ...@@ -85,9 +85,9 @@ truncated.
int my_cb(char *buf, int size, int rwflag, void *u) int my_cb(char *buf, int size, int rwflag, void *u)
{ {
strncpy(buf, (char *)u, size); strncpy(buf, (char *)u, size);
buf[size - 1] = '\0'; buf[size - 1] = '\0';
return strlen(buf); return strlen(buf);
} }
=head1 HISTORY =head1 HISTORY
......
...@@ -91,28 +91,26 @@ server id given, and will fill the rest with pseudo random bytes: ...@@ -91,28 +91,26 @@ server id given, and will fill the rest with pseudo random bytes:
#define MAX_SESSION_ID_ATTEMPTS 10 #define MAX_SESSION_ID_ATTEMPTS 10
static int generate_session_id(const SSL *ssl, unsigned char *id, static int generate_session_id(const SSL *ssl, unsigned char *id,
unsigned int *id_len) unsigned int *id_len)
{ {
unsigned int count = 0; unsigned int count = 0;
do { do {
RAND_pseudo_bytes(id, *id_len); RAND_pseudo_bytes(id, *id_len);
/* /*
* Prefix the session_id with the required prefix. NB: If our * Prefix the session_id with the required prefix. NB: If our
* prefix is too long, clip it - but there will be worse effects * prefix is too long, clip it - but there will be worse effects
* anyway, eg. the server could only possibly create 1 session * anyway, eg. the server could only possibly create 1 session
* ID (ie. the prefix!) so all future session negotiations will * ID (ie. the prefix!) so all future session negotiations will
* fail due to conflicts. * fail due to conflicts.
*/ */
memcpy(id, session_id_prefix, memcpy(id, session_id_prefix, strlen(session_id_prefix) < *id_len ?
(strlen(session_id_prefix) < *id_len) ? strlen(session_id_prefix) : *id_len);
strlen(session_id_prefix) : *id_len); } while (SSL_has_matching_session_id(ssl, id, *id_len)
} && ++count < MAX_SESSION_ID_ATTEMPTS);
while (SSL_has_matching_session_id(ssl, id, *id_len) && if (count >= MAX_SESSION_ID_ATTEMPTS)
(++count < MAX_SESSION_ID_ATTEMPTS)); return 0;
if (count >= MAX_SESSION_ID_ATTEMPTS) return 1;
return 0; }
return 1;
}
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -110,40 +110,34 @@ The following example callback function prints state strings, information ...@@ -110,40 +110,34 @@ The following example callback function prints state strings, information
about alerts being handled and error messages to the B<bio_err> BIO. about alerts being handled and error messages to the B<bio_err> BIO.
void apps_ssl_info_callback(SSL *s, int where, int ret) void apps_ssl_info_callback(SSL *s, int where, int ret)
{ {
const char *str; const char *str;
int w; int w = where & ~SSL_ST_MASK;
w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT)
str = "SSL_connect";
if (w & SSL_ST_CONNECT) str = "SSL_connect"; else if (w & SSL_ST_ACCEPT)
else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; str = "SSL_accept";
else str = "undefined"; else
str = "undefined";
if (where & SSL_CB_LOOP)
{ if (where & SSL_CB_LOOP) {
BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s)); BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
} } else if (where & SSL_CB_ALERT) {
else if (where & SSL_CB_ALERT) str = (where & SSL_CB_READ) ? "read" : "write";
{ BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", str,
str = (where & SSL_CB_READ) ? "read" : "write"; SSL_alert_type_string_long(ret),
BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", SSL_alert_desc_string_long(ret));
str, } else if (where & SSL_CB_EXIT) {
SSL_alert_type_string_long(ret), if (ret == 0) {
SSL_alert_desc_string_long(ret)); BIO_printf(bio_err, "%s:failed in %s\n",
} str, SSL_state_string_long(s));
else if (where & SSL_CB_EXIT) } else if (ret < 0) {
{ BIO_printf(bio_err, "%s:error in %s\n",
if (ret == 0) str, SSL_state_string_long(s));
BIO_printf(bio_err, "%s:failed in %s\n", }
str, SSL_state_string_long(s)); }
else if (ret < 0) }
{
BIO_printf(bio_err, "%s:error in %s\n",
str, SSL_state_string_long(s));
}
}
}
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -124,51 +124,56 @@ enable an attacker to obtain the session keys. ...@@ -124,51 +124,56 @@ enable an attacker to obtain the session keys.
=head1 EXAMPLES =head1 EXAMPLES
Reference Implementation: Reference Implementation:
SSL_CTX_set_tlsext_ticket_key_cb(SSL, ssl_tlsext_ticket_key_cb);
....
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)
{
if (enc) { /* create new session */
if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) )
return -1; /* insufficient random */
key = currentkey(); /* something that you need to implement */
if ( key == NULL ) {
/* current key doesn't exist or isn't valid */
key = createkey(); /* something that you need to implement.
* createkey needs to initialise, a name,
* an aes_key, a hmac_key and optionally
* an expire time. */
if ( key == NULL ) /* key couldn't be created */
return 0;
}
memcpy(key_name, key->name, 16);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv);
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
return 1;
} else { /* retrieve session */
key = findkey(name);
if (key == NULL || key->expire < now() )
return 0;
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv );
if (key->expire < ( now() - RENEW_TIME ) )
/* return 2 - this session will get a new ticket even though the current is still valid */
return 2;
return 1;
}
}
SSL_CTX_set_tlsext_ticket_key_cb(SSL, ssl_tlsext_ticket_key_cb);
...
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char *iv, EVP_CIPHER_CTX *ctx,
HMAC_CTX *hctx, int enc)
{
if (enc) { /* create new session */
if (RAND_bytes(iv, EVP_MAX_IV_LENGTH))
return -1; /* insufficient random */
key = currentkey(); /* something that you need to implement */
if (key == NULL) {
/* current key doesn't exist or isn't valid */
key = createkey(); /*
* Something that you need to implement.
* createkey needs to initialise a name,
* an aes_key, a hmac_key and optionally
* an expire time.
*/
if (key == NULL) /* key couldn't be created */
return 0;
}
memcpy(key_name, key->name, 16);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv);
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
return 1;
} else { /* retrieve session */
key = findkey(name);
if (key == NULL || key->expire < now())
return 0;
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv);
if (key->expire < now() - RENEW_TIME) {
/*
* return 2 - This session will get a new ticket even though the
* current one is still valid.
*/
return 2;
}
return 1;
}
}
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -84,31 +84,27 @@ supply at least 2048-bit parameters in the callback. ...@@ -84,31 +84,27 @@ supply at least 2048-bit parameters in the callback.
Setup DH parameters with a key length of 2048 bits. (Error handling Setup DH parameters with a key length of 2048 bits. (Error handling
partly left out.) partly left out.)
Command-line parameter generation: Command-line parameter generation:
$ openssl dhparam -out dh_param_2048.pem 2048 $ openssl dhparam -out dh_param_2048.pem 2048
Code for setting up parameters during server initialization: Code for setting up parameters during server initialization:
...
SSL_CTX ctx = SSL_CTX_new(); SSL_CTX ctx = SSL_CTX_new();
...
/* Set up ephemeral DH parameters. */
DH *dh_2048 = NULL; DH *dh_2048 = NULL;
FILE *paramfile; FILE *paramfile;
paramfile = fopen("dh_param_2048.pem", "r"); paramfile = fopen("dh_param_2048.pem", "r");
if (paramfile) { if (paramfile) {
dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
fclose(paramfile); fclose(paramfile);
} else { } else {
/* Error. */ /* Error. */
}
if (dh_2048 == NULL) {
/* Error. */
}
if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) {
/* Error. */
} }
if (dh_2048 == NULL)
/* Error. */
if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1)
/* Error. */
... ...
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -190,65 +190,63 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>). ...@@ -190,65 +190,63 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>).
int always_continue; int always_continue;
} mydata_t; } mydata_t;
int mydata_index; int mydata_index;
... ...
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{ {
char buf[256]; char buf[256];
X509 *err_cert; X509 *err_cert;
int err, depth; int err, depth;
SSL *ssl; SSL *ssl;
mydata_t *mydata; mydata_t *mydata;
err_cert = X509_STORE_CTX_get_current_cert(ctx); err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx); err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx); depth = X509_STORE_CTX_get_error_depth(ctx);
/* /*
* Retrieve the pointer to the SSL of the connection currently treated * Retrieve the pointer to the SSL of the connection currently treated
* and the application specific data stored into the SSL object. * and the application specific data stored into the SSL object.
*/ */
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
mydata = SSL_get_ex_data(ssl, mydata_index); mydata = SSL_get_ex_data(ssl, mydata_index);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
/* /*
* Catch a too long certificate chain. The depth limit set using * Catch a too long certificate chain. The depth limit set using
* SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so * SSL_CTX_set_verify_depth() is by purpose set to "limit+1" so
* that whenever the "depth>verify_depth" condition is met, we * that whenever the "depth>verify_depth" condition is met, we
* have violated the limit and want to log this error condition. * have violated the limit and want to log this error condition.
* We must do it here, because the CHAIN_TOO_LONG error would not * We must do it here, because the CHAIN_TOO_LONG error would not
* be found explicitly; only errors introduced by cutting off the * be found explicitly; only errors introduced by cutting off the
* additional certificates would be logged. * additional certificates would be logged.
*/ */
if (depth > mydata->verify_depth) { if (depth > mydata->verify_depth) {
preverify_ok = 0; preverify_ok = 0;
err = X509_V_ERR_CERT_CHAIN_TOO_LONG; err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
X509_STORE_CTX_set_error(ctx, err); X509_STORE_CTX_set_error(ctx, err);
} }
if (!preverify_ok) { if (!preverify_ok) {
printf("verify error:num=%d:%s:depth=%d:%s\n", err, printf("verify error:num=%d:%s:depth=%d:%s\n", err,
X509_verify_cert_error_string(err), depth, buf); X509_verify_cert_error_string(err), depth, buf);
} } else if (mydata->verbose_mode) {
else if (mydata->verbose_mode) printf("depth=%d:%s\n", depth, buf);
{ }
printf("depth=%d:%s\n", depth, buf);
} /*
* At this point, err contains the last verification error. We can use
/* * it for something special
* At this point, err contains the last verification error. We can use */
* it for something special if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
*/ X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) printf("issuer= %s\n", buf);
{ }
X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
printf("issuer= %s\n", buf); if (mydata->always_continue)
} return 1;
else
if (mydata->always_continue) return preverify_ok;
return 1;
else
return preverify_ok;
} }
... ...
...@@ -258,7 +256,7 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>). ...@@ -258,7 +256,7 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>).
mydata_index = SSL_get_ex_new_index(0, "mydata index", NULL, NULL, NULL); mydata_index = SSL_get_ex_new_index(0, "mydata index", NULL, NULL, NULL);
... ...
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE,
verify_callback); verify_callback);
/* /*
...@@ -276,12 +274,10 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>). ...@@ -276,12 +274,10 @@ L<SSL_get_ex_data_X509_STORE_CTX_idx(3)>).
... ...
SSL_accept(ssl); /* check of success left out for clarity */ SSL_accept(ssl); /* check of success left out for clarity */
if (peer = SSL_get_peer_certificate(ssl)) if (peer = SSL_get_peer_certificate(ssl)) {
{ if (SSL_get_verify_result(ssl) == X509_V_OK) {
if (SSL_get_verify_result(ssl) == X509_V_OK) /* The client sent a certificate which verified OK */
{ }
/* The client sent a certificate which verified OK */
}
} }
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -33,9 +33,9 @@ Load names of CAs from file and use it as a client CA list: ...@@ -33,9 +33,9 @@ Load names of CAs from file and use it as a client CA list:
... ...
cert_names = SSL_load_client_CA_file("/path/to/CAfile.pem"); cert_names = SSL_load_client_CA_file("/path/to/CAfile.pem");
if (cert_names != NULL) if (cert_names != NULL)
SSL_CTX_set_client_CA_list(ctx, cert_names); SSL_CTX_set_client_CA_list(ctx, cert_names);
else else
error_handling(); /* error */
... ...
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -81,23 +81,20 @@ matched in the certificate (which might be a wildcard) is retrieved, ...@@ -81,23 +81,20 @@ matched in the certificate (which might be a wildcard) is retrieved,
and must be copied by the application if it is to be retained beyond and must be copied by the application if it is to be retained beyond
the lifetime of the SSL connection. the lifetime of the SSL connection.
SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
if (!SSL_set1_host(ssl, "smtp.example.com")) { if (!SSL_set1_host(ssl, "smtp.example.com"))
/* handle error */ /* error */
} if (!SSL_add1_host(ssl, "example.com"))
if (!SSL_add1_host(ssl, "example.com")) { /* error */
/* handle error */
} /* XXX: Perform SSL_connect() handshake and handle errors here */
/* XXX: Perform SSL_connect() handshake and handle errors here */ if (SSL_get_verify_result(ssl) == X509_V_OK) {
const char *peername = SSL_get0_peername(ssl);
if (SSL_get_verify_result(ssl) == X509_V_OK) {
const char *peername = SSL_get0_peername(ssl); if (peername != NULL)
/* Name checks were in scope and matched the peername */
if (peername != NULL) { }
/* Name checks were in scope and matched the peername */
}
}
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -80,16 +80,16 @@ Create an B<X509_NAME> structure: ...@@ -80,16 +80,16 @@ Create an B<X509_NAME> structure:
X509_NAME *nm; X509_NAME *nm;
nm = X509_NAME_new(); nm = X509_NAME_new();
if (nm == NULL) if (nm == NULL)
/* Some error */ /* Some error */
if (!X509_NAME_add_entry_by_txt(nm, "C", MBSTRING_ASC, if (!X509_NAME_add_entry_by_txt(nm, "C", MBSTRING_ASC,
"UK", -1, -1, 0)) "UK", -1, -1, 0))
/* Error */ /* Error */
if (!X509_NAME_add_entry_by_txt(nm, "O", MBSTRING_ASC, if (!X509_NAME_add_entry_by_txt(nm, "O", MBSTRING_ASC,
"Disorganized Organization", -1, -1, 0)) "Disorganized Organization", -1, -1, 0))
/* Error */ /* Error */
if (!X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, if (!X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC,
"Joe Bloggs", -1, -1, 0)) "Joe Bloggs", -1, -1, 0))
/* Error */ /* Error */
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -75,25 +75,23 @@ Process all entries: ...@@ -75,25 +75,23 @@ Process all entries:
int i; int i;
X509_NAME_ENTRY *e; X509_NAME_ENTRY *e;
for (i = 0; i < X509_NAME_entry_count(nm); i++) for (i = 0; i < X509_NAME_entry_count(nm); i++) {
{ e = X509_NAME_get_entry(nm, i);
e = X509_NAME_get_entry(nm, i); /* Do something with e */
/* Do something with e */ }
}
Process all commonName entries: Process all commonName entries:
int lastpos = -1; int lastpos = -1;
X509_NAME_ENTRY *e; X509_NAME_ENTRY *e;
for (;;) for (;;) {
{ lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos);
lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos); if (lastpos == -1)
if (lastpos == -1) break;
break; e = X509_NAME_get_entry(nm, lastpos);
e = X509_NAME_get_entry(nm, lastpos); /* Do something with e */
/* Do something with e */ }
}
=head1 RETURN VALUES =head1 RETURN VALUES
......
...@@ -70,7 +70,7 @@ is B<not> successful the returned chain may be incomplete or invalid. The ...@@ -70,7 +70,7 @@ is B<not> successful the returned chain may be incomplete or invalid. The
returned chain persists after the B<ctx> structure is freed, when it is returned chain persists after the B<ctx> structure is freed, when it is
no longer needed it should be free up using: no longer needed it should be free up using:
sk_X509_pop_free(chain, X509_free); sk_X509_pop_free(chain, X509_free);
X509_verify_cert_error_string() returns a human readable error string for X509_verify_cert_error_string() returns a human readable error string for
verification error B<n>. verification error B<n>.
......
...@@ -100,93 +100,88 @@ X509_STORE_CTX_set_verify_cb() does not return a value. ...@@ -100,93 +100,88 @@ X509_STORE_CTX_set_verify_cb() does not return a value.
Default callback operation: Default callback operation:
int verify_callback(int ok, X509_STORE_CTX *ctx) int verify_callback(int ok, X509_STORE_CTX *ctx) {
{ return ok;
return ok; }
}
Simple example, suppose a certificate in the chain is expired and we wish Simple example, suppose a certificate in the chain is expired and we wish
to continue after this error: to continue after this error:
int verify_callback(int ok, X509_STORE_CTX *ctx) int verify_callback(int ok, X509_STORE_CTX *ctx) {
{ /* Tolerate certificate expiration */
/* Tolerate certificate expiration */ if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED)
if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED) return 1;
return 1; /* Otherwise don't override */
/* Otherwise don't override */ return ok;
return ok; }
}
More complex example, we don't wish to continue after B<any> certificate has More complex example, we don't wish to continue after B<any> certificate has
expired just one specific case: expired just one specific case:
int verify_callback(int ok, X509_STORE_CTX *ctx) int verify_callback(int ok, X509_STORE_CTX *ctx)
{ {
int err = X509_STORE_CTX_get_error(ctx); int err = X509_STORE_CTX_get_error(ctx);
X509 *err_cert = X509_STORE_CTX_get_current_cert(ctx); X509 *err_cert = X509_STORE_CTX_get_current_cert(ctx);
if (err == X509_V_ERR_CERT_HAS_EXPIRED) if (err == X509_V_ERR_CERT_HAS_EXPIRED) {
{ if (check_is_acceptable_expired_cert(err_cert)
if (check_is_acceptable_expired_cert(err_cert) return 1;
return 1; }
} return ok;
return ok; }
}
Full featured logging callback. In this case the B<bio_err> is assumed to be Full featured logging callback. In this case the B<bio_err> is assumed to be
a global logging B<BIO>, an alternative would to store a BIO in B<ctx> using a global logging B<BIO>, an alternative would to store a BIO in B<ctx> using
B<ex_data>. B<ex_data>.
int verify_callback(int ok, X509_STORE_CTX *ctx) int verify_callback(int ok, X509_STORE_CTX *ctx)
{ {
X509 *err_cert; X509 *err_cert;
int err, depth; int err, depth;
err_cert = X509_STORE_CTX_get_current_cert(ctx); err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx); err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx); depth = X509_STORE_CTX_get_error_depth(ctx);
BIO_printf(bio_err, "depth=%d ", depth); BIO_printf(bio_err, "depth=%d ", depth);
if (err_cert) if (err_cert) {
{ X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert),
X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert), 0, XN_FLAG_ONELINE);
0, XN_FLAG_ONELINE); BIO_puts(bio_err, "\n");
BIO_puts(bio_err, "\n"); }
} else
else BIO_puts(bio_err, "<no cert>\n");
BIO_puts(bio_err, "<no cert>\n"); if (!ok)
if (!ok) BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
BIO_printf(bio_err, "verify error:num=%d:%s\n", err, X509_verify_cert_error_string(err));
X509_verify_cert_error_string(err)); switch (err) {
switch (err) case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
{ BIO_puts(bio_err, "issuer= ");
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
BIO_puts(bio_err, "issuer= "); 0, XN_FLAG_ONELINE);
X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), BIO_puts(bio_err, "\n");
0, XN_FLAG_ONELINE); break;
BIO_puts(bio_err, "\n"); case X509_V_ERR_CERT_NOT_YET_VALID:
break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
case X509_V_ERR_CERT_NOT_YET_VALID: BIO_printf(bio_err, "notBefore=");
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert));
BIO_printf(bio_err, "notBefore="); BIO_printf(bio_err, "\n");
ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert)); break;
BIO_printf(bio_err, "\n"); case X509_V_ERR_CERT_HAS_EXPIRED:
break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
case X509_V_ERR_CERT_HAS_EXPIRED: BIO_printf(bio_err, "notAfter=");
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert));
BIO_printf(bio_err, "notAfter="); BIO_printf(bio_err, "\n");
ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert)); break;
BIO_printf(bio_err, "\n"); case X509_V_ERR_NO_EXPLICIT_POLICY:
break; policies_print(bio_err, ctx);
case X509_V_ERR_NO_EXPLICIT_POLICY: break;
policies_print(bio_err, ctx); }
break; if (err == X509_V_OK && ok == 2)
} /* print out policies */
if (err == X509_V_OK && ok == 2)
/* print out policies */ BIO_printf(bio_err, "verify return:%d\n", ok);
return(ok);
BIO_printf(bio_err, "verify return:%d\n", ok); }
return(ok);
}
=head1 SEE ALSO =head1 SEE ALSO
......
...@@ -310,11 +310,11 @@ CRLs from the CRL distribution points extension. ...@@ -310,11 +310,11 @@ CRLs from the CRL distribution points extension.
Enable CRL checking when performing certificate verification during SSL Enable CRL checking when performing certificate verification during SSL
connections associated with an B<SSL_CTX> structure B<ctx>: connections associated with an B<SSL_CTX> structure B<ctx>:
X509_VERIFY_PARAM *param; X509_VERIFY_PARAM *param;
param = X509_VERIFY_PARAM_new(); param = X509_VERIFY_PARAM_new();
X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
SSL_CTX_set1_param(ctx, param); SSL_CTX_set1_param(ctx, param);
X509_VERIFY_PARAM_free(param); X509_VERIFY_PARAM_free(param);
=head1 SEE ALSO =head1 SEE ALSO
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册