Adding in curl and openssl repos

This commit is contained in:
2025-08-14 12:09:30 -04:00
parent af2117b574
commit 0ace93e303
21174 changed files with 3607720 additions and 2 deletions

View File

@@ -0,0 +1,28 @@
MODULES = bio \
cipher \
cms \
digest \
encode \
encrypt \
guide \
http3 \
kdf \
keyexch \
mac \
pkey \
signature \
smime \
sslecho
all:
@set -e; for i in $(MODULES); do \
${MAKE} -C $$i all; \
done
clean:
@set -e; for i in $(MODULES); do \
${MAKE} -C $$i clean; \
done
test:
@set -e; for i in $(MODULES); do \
${MAKE} -C $$i test; \
done

View File

@@ -0,0 +1,81 @@
OpenSSL Demonstration Applications
This folder contains source code that demonstrates the proper use of the OpenSSL
library API.
Note: Makefiles are provided in the demo subfolders to demonstrate how to build
them, but are not frequently used. Configure openssl with enable-demos to build
them automatically through the perl based build system
bio: Demonstration of a simple TLS client and server
certs: Demonstration of creating certs, using OCSP
cipher:
aesgcm.c Demonstration of symmetric cipher GCM mode encrypt/decrypt
aesccm.c Demonstration of symmetric cipher CCM mode encrypt/decrypt
ariacbc.c Demonstration of symmetric cipher CBC mode encrypt/decrypt
cms: Demonstrations related to the Cryptographic Message
Syntax (CMS) standard
digest:
EVP_MD_demo.c Compute a digest from multiple buffers
EVP_MD_stdin.c Compute a digest with data read from stdin
EVP_MD_xof.c Compute a digest using the SHAKE256 XOF
EVP_f_md.c Compute a digest using BIO and EVP_f_md
encode:
rsa_encode.c Encode and decode PEM-encoded RSA keys
encrypt:
rsa_encrypt.c Encrypt and decrypt data using an RSA keypair.
guide: Sample code from the OpenSSL Guide tutorials. See
the oss-guide-quic-introduction(7) man page.
quic-client-block.c: A simple blocking QUIC client
quic-client-non-block.c: A simple non-blocking QUIC client
quic-multi-stream.c: A simple QUIC client using multiple streams
tls-client-block.c: A simple blocking SSL/TLS client
tls-client-non-block.c: A simple non-blocking SSL/TLS client
http3: Demonstration of how to use OpenSSL's QUIC capabilities
for HTTP/3.
kdf:
hkdf.c Demonstration of HMAC based key derivation
pbkdf2.c Demonstration of PBKDF2 password based key derivation
scrypt.c Demonstration of SCRYPT password based key derivation
keyexch:
x25519.c Demonstration of X25519 based key exchange
ecdh.c Demonstration of ECDH key exchange
mac:
gmac.c Demonstration of GMAC message authentication
poly1305.c Demonstration of Poly1305-AES message authentication
siphash.c Demonstration of SIPHASH message authentication
pkcs12:
pkread.c Print out a description of a PKCS12 file.
pkwrite.c Add a password to an existing PKCS12 file.
pkey:
EVP_PKEY_EC_keygen.c Generate an EC key.
EVP_PKEY_RSA_keygen.c Generate an RSA key.
EVP_PKEY_DSA_keygen.c Generate a DSA key.
EVP_PKEY_DSA_paramgen.c Generate a DSA param key.
EVP_PKEY_DSA_paramvalidate.c Validate a DSA param key.
EVP_PKEY_DSA_paramfromdata.c Load a DSA param key using raw data.
signature:
EVP_EC_Signature_demo.c Compute and verify an EC signature.
EVP_DSA_Signature_demo.c Compute and verify a DSA signature.
EVP_ED_Signature_demo.c Compute and verify an ED25519 signature.
rsa_pss_direct.c Compute and verify an RSA-PSS signature from a hash
rsa_pss_hash.c Compute and verify an RSA-PSS signature over a buffer
smime: Demonstrations related to S/MIME
sslecho:
main.c Simple SSL/TLS echo client/server.

View File

@@ -0,0 +1,37 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto and libssl are on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./server-arg
TESTS = client-arg \
client-conf \
saccept \
sconnect \
server-arg \
server-cmod \
server-conf
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lssl -lcrypto
all: $(TESTS)
client-arg: client-arg.o
client-conf: client-conf.o
saccept: saccept.o
sconnect: sconnect.o
server-arg: server-arg.o
server-cmod: server-cmod.o
server-conf: server-conf.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) $(TESTS) *.o
test: all
@echo "\nBIO tests:"
@echo "skipped"

View File

@@ -0,0 +1,6 @@
This directory contains some simple examples of the use of BIO's
to simplify socket programming.
The client-conf, server-conf, client-arg and client-conf include examples
of how to use the SSL_CONF API for configuration file or command line
processing.

View File

@@ -0,0 +1,23 @@
# Example configuration file
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
# Port to listen on
Port = 4433
# Disable TLS v1.2 for test.
# Protocol = ALL, -TLSv1.2
# Only support 3 curves
Curves = P-521:P-384:P-256
# Restricted signature algorithms
SignatureAlgorithms = RSA+SHA512:ECDSA+SHA512
Certificate=server.pem
PrivateKey=server.pem
ChainCAFile=root.pem
VerifyCAFile=root.pem
# Request certificate
VerifyMode=Request
ClientCAFile=root.pem

View File

@@ -0,0 +1,29 @@
PROGRAMS{noinst}=client-arg sconnect server-cmod client-conf saccept server-arg server-conf
INCLUDE[client-arg]=../../include
SOURCE[client-arg]=client-arg.c
DEPEND[client-arg]=../../libcrypto ../../libssl
INCLUDE[sconnect]=../../include
SOURCE[sconnect]=sconnect.c
DEPEND[sconnect]=../../libcrypto ../../libssl
INCLUDE[server-cmod]=../../include
SOURCE[server-cmod]=server-cmod.c
DEPEND[server-cmod]=../../libcrypto ../../libssl
INCLUDE[client-conf]=../../include
SOURCE[client-conf]=client-conf.c
DEPEND[client-conf]=../../libcrypto ../../libssl
INCLUDE[saccept]=../../include
SOURCE[saccept]=saccept.c
DEPEND[saccept]=../../libcrypto ../../libssl
INCLUDE[server-arg]=../../include
SOURCE[server-arg]=server-arg.c
DEPEND[server-arg]=../../libcrypto ../../libssl
INCLUDE[server-conf]=../../include
SOURCE[server-conf]=server-conf.c
DEPEND[server-conf]=../../libcrypto ../../libssl

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2013-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
int main(int argc, char **argv)
{
BIO *sbio = NULL, *out = NULL;
int len;
char tmpbuf[1024];
SSL_CTX *ctx;
SSL_CONF_CTX *cctx;
SSL *ssl;
char **args = argv + 1;
const char *connect_str = "localhost:4433";
int nargs = argc - 1;
int ret = EXIT_FAILURE;
ctx = SSL_CTX_new(TLS_client_method());
cctx = SSL_CONF_CTX_new();
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
while (*args && **args == '-') {
int rv;
/* Parse standard arguments */
rv = SSL_CONF_cmd_argv(cctx, &nargs, &args);
if (rv == -3) {
fprintf(stderr, "Missing argument for %s\n", *args);
goto end;
}
if (rv < 0) {
fprintf(stderr, "Error in command %s\n", *args);
ERR_print_errors_fp(stderr);
goto end;
}
/* If rv > 0 we processed something so proceed to next arg */
if (rv > 0)
continue;
/* Otherwise application specific argument processing */
if (strcmp(*args, "-connect") == 0) {
connect_str = args[1];
if (connect_str == NULL) {
fprintf(stderr, "Missing -connect argument\n");
goto end;
}
args += 2;
nargs -= 2;
continue;
} else {
fprintf(stderr, "Unknown argument %s\n", *args);
goto end;
}
}
if (!SSL_CONF_CTX_finish(cctx)) {
fprintf(stderr, "Finish error\n");
ERR_print_errors_fp(stderr);
goto end;
}
/*
* We'd normally set some stuff like the verify paths and * mode here
* because as things stand this will connect to * any server whose
* certificate is signed by any CA.
*/
sbio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(sbio, &ssl);
if (!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
goto end;
}
/* We might want to do other things with ssl here */
BIO_set_conn_hostname(sbio, connect_str);
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if (BIO_do_connect(sbio) <= 0) {
fprintf(stderr, "Error connecting to server\n");
ERR_print_errors_fp(stderr);
goto end;
}
/* Could examine ssl here to get connection info */
BIO_puts(sbio, "GET / HTTP/1.0\n\n");
for (;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if (len <= 0)
break;
BIO_write(out, tmpbuf, len);
}
ret = EXIT_SUCCESS;
end:
SSL_CONF_CTX_free(cctx);
BIO_free_all(sbio);
BIO_free(out);
return ret;
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2013-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>
int main(int argc, char **argv)
{
BIO *sbio = NULL, *out = NULL;
int i, len, rv;
char tmpbuf[1024];
SSL_CTX *ctx = NULL;
SSL_CONF_CTX *cctx = NULL;
SSL *ssl = NULL;
CONF *conf = NULL;
STACK_OF(CONF_VALUE) *sect = NULL;
CONF_VALUE *cnf;
const char *connect_str = "localhost:4433";
long errline = -1;
int ret = EXIT_FAILURE;
conf = NCONF_new(NULL);
if (NCONF_load(conf, "connect.cnf", &errline) <= 0) {
if (errline <= 0)
fprintf(stderr, "Error processing config file\n");
else
fprintf(stderr, "Error on line %ld\n", errline);
goto end;
}
sect = NCONF_get_section(conf, "default");
if (sect == NULL) {
fprintf(stderr, "Error retrieving default section\n");
goto end;
}
ctx = SSL_CTX_new(TLS_client_method());
cctx = SSL_CONF_CTX_new();
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
cnf = sk_CONF_VALUE_value(sect, i);
rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value);
if (rv > 0)
continue;
if (rv != -2) {
fprintf(stderr, "Error processing %s = %s\n",
cnf->name, cnf->value);
ERR_print_errors_fp(stderr);
goto end;
}
if (strcmp(cnf->name, "Connect") == 0) {
connect_str = cnf->value;
} else {
fprintf(stderr, "Unknown configuration option %s\n", cnf->name);
goto end;
}
}
if (!SSL_CONF_CTX_finish(cctx)) {
fprintf(stderr, "Finish error\n");
ERR_print_errors_fp(stderr);
goto end;
}
/*
* We'd normally set some stuff like the verify paths and * mode here
* because as things stand this will connect to * any server whose
* certificate is signed by any CA.
*/
sbio = BIO_new_ssl_connect(ctx);
BIO_get_ssl(sbio, &ssl);
if (!ssl) {
fprintf(stderr, "Can't locate SSL pointer\n");
goto end;
}
/* We might want to do other things with ssl here */
BIO_set_conn_hostname(sbio, connect_str);
out = BIO_new_fp(stdout, BIO_NOCLOSE);
if (BIO_do_connect(sbio) <= 0) {
fprintf(stderr, "Error connecting to server\n");
ERR_print_errors_fp(stderr);
goto end;
}
/* Could examine ssl here to get connection info */
BIO_puts(sbio, "GET / HTTP/1.0\n\n");
for (;;) {
len = BIO_read(sbio, tmpbuf, 1024);
if (len <= 0)
break;
BIO_write(out, tmpbuf, len);
}
ret = EXIT_SUCCESS;
end:
SSL_CONF_CTX_free(cctx);
BIO_free_all(sbio);
BIO_free(out);
NCONF_free(conf);
return ret;
}

View File

@@ -0,0 +1,27 @@
# Example config module configuration
# Name supplied by application to CONF_modules_load_file
# and section containing configuration
testapp = test_sect
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
[test_sect]
# list of configuration modules
# SSL configuration module
ssl_conf = ssl_sect
[ssl_sect]
# list of SSL configurations
server = server_sect
[server_sect]
# Only support 3 curves
Curves = P-521:P-384:P-256
# Restricted signature algorithms
SignatureAlgorithms = RSA+SHA512:ECDSA+SHA512
# Certificates and keys
RSA.Certificate=server.pem
ECDSA.Certificate=server-ec.pem

View File

@@ -0,0 +1,15 @@
# Example configuration file
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
# Connects to the default port of s_server
Connect = localhost:4433
# Disable TLS v1.2 for test.
# Protocol = ALL, -TLSv1.2
# Only support 3 curves
Curves = P-521:P-384:P-256
# Restricted signature algorithms
SignatureAlgorithms = RSA+SHA512:ECDSA+SHA512

View File

@@ -0,0 +1,47 @@
# This build description trusts that the following logical names are defined:
#
# For compilation: OPENSSL
# For linking with shared libraries: OSSL$LIBCRYPTO_SHR and OSSL$LIBSSL_SHR
# For linking with static libraries: OSSL$LIBCRYPTO and OSSL$LIBSSL
#
# These are normally defined with the OpenSSL startup procedure
# By default, we link with the shared libraries
SHARED = TRUE
# Alternative, for linking with static libraries
#SHARED = FALSE
.FIRST :
IF "$(SHARED)" .EQS. "TRUE" THEN DEFINE OPT []shared.opt
IF "$(SHARED)" .NES. "TRUE" THEN DEFINE OPT []static.opt
.LAST :
DEASSIGN OPT
.DEFAULT :
@ !
# Because we use an option file, we need to redefine this
.obj.exe :
$(LINK) $(LINKFLAGS) $<,OPT:/OPT
all : client-arg.exe client-conf.exe saccept.exe sconnect.exe -
server-arg.exe server-cmod.exe server-conf.exe
client-arg.exe : client-arg.obj
client-conf.exe : client-conf.obj
saccept.exe : saccept.obj
sconnect.exe : sconnect.obj
server-arg.exe : server-arg.obj
server-cmod.exe : server-cmod.obj
server-conf.exe : server-conf.obj
# MMS doesn't infer this automatically...
client-arg.obj : client-arg.c
client-conf.obj : client-conf.c
saccept.obj : saccept.c
sconnect.obj : sconnect.c
server-arg.obj : server-arg.c
server-cmod.obj : server-cmod.c
server-conf.obj : server-conf.c

View File

@@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEPzCCAqegAwIBAgIILsaQqJAjK4IwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UE
BhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNU
SU5HIFBVUlBPU0VTIE9OTFkxHTAbBgNVBAMMFE9wZW5TU0wgVGVzdCBSb290IENB
MCAXDTE4MDYxNDEyNDYyOFoYDzIxMTgwNjE0MTI0NjI4WjBwMQswCQYDVQQGEwJV
SzEWMBQGA1UECgwNT3BlblNTTCBHcm91cDEiMCAGA1UECwwZRk9SIFRFU1RJTkcg
UFVSUE9TRVMgT05MWTElMCMGA1UEAwwcT3BlblNTTCBUZXN0IEludGVybWVkaWF0
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANIpVng2wNFJp2kF
oJ6Yji25wy1YufnS8NxA82fk5OHdhGWj1CWqnQNotEqEQzcOUszQYrNxd8tEvoWk
Ik4JMBVoEcgBGedchftptTNulFWodWpi1yFaqA/Nz2BsVgcCJW4C+UWDT7VeHtGU
7tYKKr35lxp6io/a4jUDQXvO2nJA9YlrxOktunMqtoZSYqUz35ZXsdkn58o8Fbqm
dEpw6AqAr9aBgY5DSaGxbaX2lwNt9NvB+f9ucOqEnPP8AfTlPYc/ENwJ6u/H8RGw
d1im71mu2lHjcws3aHkbluH860U3vlKWx6Ff1qdQcH98e2HwElqxCK00xya8leu4
u64nljkCAwEAAaNjMGEwHQYDVR0OBBYEFAoDRKVoOufDXW5Ui7L4ONxANVsFMB8G
A1UdIwQYMBaAFDZjTeLsQUG6KL9xuLhzXVdB4pkKMA8GA1UdEwEB/wQFMAMBAf8w
DgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBgQDZQJLA90ewVaS3E3du
gSjPkQ1xsHm8H1am+7zr5oZ81J+R8XYIZgMR+9ShVo38OradiYNqDLso+4iuVdxh
hzoSoQELoDXCficzWKnlAtWvwDDoczyK+/p94g3VKx14n2+GvQzoZ4kwQQgaFH1w
YI6w0oH9zwoklCxvihj8D069QrYyuTT8JGZ2m0FHqVJg6teuQKFahSgwYR2CUoIb
6PrpSUQeCVCH8TPkzlRT6UgtM3ERt7+TlQ+zZ80dSf4YTAsDv9Z/CJXiF/5wZr6/
lWuFjWmX2HkpEW6Wiv5KF8QP6Ft7Z+RYua7RMtELCYvqYbWDBs7fXWGBkZ5xhB09
jCxz+F7zOeRbyzacfFq9DhxCWCRbIrdgGGE/Of2ujJtmK/2p4M6E5IsKNAI2SJBW
iJXvIgQgR22ehPqy6er2Gog5LkWUwqB0kHZJJpbp1IW01IGTpD6YAJyVCEAlyMbo
Kto9+wQFLT3Auv/W5h6OwxkNdfAyZBYy0ZSFk4EE8OdWWY4=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIEwzCCAyugAwIBAgIUHKKc7fxVgQjWQ7IF6l7m/fHQHH8wDQYJKoZIhvcNAQEL
BQAwaDELMAkGA1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNV
BAsMGUZPUiBURVNUSU5HIFBVUlBPU0VTIE9OTFkxHTAbBgNVBAMMFE9wZW5TU0wg
VGVzdCBSb290IENBMCAXDTE4MDYxNDEyNDYyOFoYDzIxMTgwNjE0MTI0NjI4WjBo
MQswCQYDVQQGEwJVSzEWMBQGA1UECgwNT3BlblNTTCBHcm91cDEiMCAGA1UECwwZ
Rk9SIFRFU1RJTkcgUFVSUE9TRVMgT05MWTEdMBsGA1UEAwwUT3BlblNTTCBUZXN0
IFJvb3QgQ0EwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDaTVriXS5C
6C17OxGwWR4xxdLveLLkAb0+nSiYpzfCcEGX3qiBxHDA+Nj1kkihIJNkXmrKxa3w
1XIVoSUaVULuVxe3vqla+DScGC9MLVsfIwWe8UdGsKst4VvvtNvQUZ5CvLF4jv0V
nabvQhcjY5X7A/t8cZcjOHcaZ9fkThhG/7tJKwp4dLgPcXIimQ0UtP5gRBxnpEYd
l21mPjafqPt02lfOWTgnT5PeVoBDmN7QcrTlI7RzaeDglwFm10rNuYsRxrVsEfiG
Ejup/1eM/69zkV4Lb2RFbIpZ+oKqQ5AEemh6/IP9VwX08DOX3T1EqwthyB+yOZgp
BQ/MZ2M21E03sxlgPGKkRVTU520az84Tyft7T7sJ6BeGSMrdEZVUSJxsS/iFFwL2
ubmhG6tq0ALIyoS+rUeHUeH2pVnEEcHIXAsLbCXfmsRpWU1fOHcpkTSzbMPhqMa3
K8aKNHni0UtoD+ddOw0Zrx4uf3zlbPCzy2eQ2d8qb/TSynGxWmN8an8CAwEAAaNj
MGEwHQYDVR0OBBYEFDZjTeLsQUG6KL9xuLhzXVdB4pkKMB8GA1UdIwQYMBaAFDZj
TeLsQUG6KL9xuLhzXVdB4pkKMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
AgEGMA0GCSqGSIb3DQEBCwUAA4IBgQCFbQA4yoXhxVQm+tEMpfKf2VEzQVNw0Tzd
Vy+zbscQ04RM4Hx4YbICdX+J7M2fYByU+KawllZJI++mfS9sbnuPIouD5NJLX5EH
//5rySOqA0OkN/Y8f41xp/YF5j96NUCjg3RoerefRSHZfNWJE1faQEHuhwDZK6OQ
GNgt246FZ7ittfe537MHUWY7CjKt6kILN03rVKSgRwwOw5Tv+VyUVyUtRppWl57L
Z+41g0gZ/r7h6ACd+n35nuzgbmqUF2VNYQLo7RzaxPvtkzJ4t96r+5NAr1cx8thr
3rnJWSgpm1ZKdtHMj1jCLxarn8gNz2gB35Tn2NdzHQI0/aEEcfLWpU9mrmhUW+yy
WEN2R8BqGsC++HhlUKKJZgR48SHF5MOBl4KyZPylBuPYcJFQdnEbioBLPlvt5bbt
+o/w3sCR3ZVHMB0n9OcQwd6tdN7aDiept6lJPlOp4dfFjkku8J5nM0oY/Xsg194A
rRK0SBUCVN/2NSHFl9LKEqQiQIUjOQM=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,125 @@
/*
* Copyright 1998-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* A minimal program to serve an SSL connection.
* It uses blocking.
* saccept host:port
* host is the interface IP to use. If any interface, use *:port
* The default it *:4433
*
* cc -I../../include saccept.c -L../.. -lssl -lcrypto -ldl
*/
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#define CERT_FILE "server.pem"
static volatile int done = 0;
static void interrupt(int sig)
{
done = 1;
}
static void sigsetup(void)
{
#if defined(OPENSSL_SYS_WINDOWS)
signal(SIGINT, interrupt);
#else
struct sigaction sa;
/*
* Catch at most once, and don't restart the accept system call.
*/
sa.sa_flags = SA_RESETHAND;
sa.sa_handler = interrupt;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
#endif
}
int main(int argc, char *argv[])
{
char *port = NULL;
BIO *in = NULL;
BIO *ssl_bio, *tmp;
SSL_CTX *ctx;
char buf[512];
int ret = EXIT_FAILURE, i;
if (argc <= 1)
port = "*:4433";
else
port = argv[1];
ctx = SSL_CTX_new(TLS_server_method());
if (!SSL_CTX_use_certificate_chain_file(ctx, CERT_FILE))
goto err;
if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM))
goto err;
if (!SSL_CTX_check_private_key(ctx))
goto err;
/* Setup server side SSL bio */
ssl_bio = BIO_new_ssl(ctx, 0);
if ((in = BIO_new_accept(port)) == NULL)
goto err;
/*
* This means that when a new connection is accepted on 'in', The ssl_bio
* will be 'duplicated' and have the new socket BIO push into it.
* Basically it means the SSL BIO will be automatically setup
*/
BIO_set_accept_bios(in, ssl_bio);
/* Arrange to leave server loop on interrupt */
sigsetup();
again:
/*
* The first call will setup the accept socket, and the second will get a
* socket. In this loop, the first actual accept will occur in the
* BIO_read() function.
*/
if (BIO_do_accept(in) <= 0)
goto err;
while (!done) {
i = BIO_read(in, buf, 512);
if (i == 0) {
/*
* If we have finished, remove the underlying BIO stack so the
* next time we call any function for this BIO, it will attempt
* to do an accept
*/
printf("Done\n");
tmp = BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i < 0)
goto err;
fwrite(buf, 1, i, stdout);
fflush(stdout);
}
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
BIO_free(in);
return ret;
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* A minimal program to do SSL to a passed host and port.
* It is actually using non-blocking IO but in a very simple manner
* sconnect host:port - it does a 'GET / HTTP/1.0'
*
* cc -I../../include sconnect.c -L../.. -lssl -lcrypto
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#if !defined(OPENSSL_SYS_WINDOWS)
#include <unistd.h>
#else
#include <windows.h>
# define sleep(x) Sleep(x*1000)
#endif
#define HOSTPORT "localhost:4433"
#define CAFILE "root.pem"
int main(int argc, char *argv[])
{
const char *hostport = HOSTPORT;
const char *CAfile = CAFILE;
const char *hostname;
BIO *out = NULL;
char buf[1024 * 10], *p;
SSL_CTX *ssl_ctx = NULL;
SSL *ssl;
BIO *ssl_bio;
int i, len, off, ret = EXIT_FAILURE;
if (argc > 1)
hostport = argv[1];
if (argc > 2)
CAfile = argv[2];
#ifdef WATT32
dbug_init();
sock_init();
#endif
ssl_ctx = SSL_CTX_new(TLS_client_method());
/* Enable trust chain verification */
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
if (!SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL))
goto err;
/* Lets make a SSL structure */
ssl = SSL_new(ssl_ctx);
SSL_set_connect_state(ssl);
/* Use it inside an SSL BIO */
ssl_bio = BIO_new(BIO_f_ssl());
BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
/* Lets use a connect BIO under the SSL BIO */
out = BIO_new(BIO_s_connect());
BIO_set_conn_hostname(out, hostport);
/* The BIO has parsed the host:port and even IPv6 literals in [] */
hostname = BIO_get_conn_hostname(out);
if (!hostname || SSL_set1_host(ssl, hostname) <= 0) {
BIO_free(ssl_bio);
goto err;
}
BIO_set_nbio(out, 1);
out = BIO_push(ssl_bio, out);
p = "GET / HTTP/1.0\r\n\r\n";
len = strlen(p);
off = 0;
for (;;) {
i = BIO_write(out, &(p[off]), len);
if (i <= 0) {
if (BIO_should_retry(out)) {
fprintf(stderr, "write DELAY\n");
sleep(1);
continue;
} else {
goto err;
}
}
off += i;
len -= i;
if (len <= 0)
break;
}
for (;;) {
i = BIO_read(out, buf, sizeof(buf));
if (i == 0)
break;
if (i < 0) {
if (BIO_should_retry(out)) {
fprintf(stderr, "read DELAY\n");
sleep(1);
continue;
}
goto err;
}
fwrite(buf, 1, i, stdout);
}
ret = EXIT_SUCCESS;
goto done;
err:
if (ERR_peek_error() == 0) { /* system call error */
fprintf(stderr, "errno=%d ", errno);
perror("error");
} else {
ERR_print_errors_fp(stderr);
}
done:
BIO_free_all(out);
SSL_CTX_free(ssl_ctx);
return ret;
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* A minimal program to serve an SSL connection. It uses blocking. It use the
* SSL_CONF API with the command line. cc -I../../include server-arg.c
* -L../.. -lssl -lcrypto -ldl
*/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
int main(int argc, char *argv[])
{
char *port = "*:4433";
BIO *ssl_bio, *tmp;
SSL_CTX *ctx;
SSL_CONF_CTX *cctx;
char buf[512];
BIO *in = NULL;
int ret = EXIT_FAILURE, i;
char **args = argv + 1;
int nargs = argc - 1;
ctx = SSL_CTX_new(TLS_server_method());
cctx = SSL_CONF_CTX_new();
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
while (*args && **args == '-') {
int rv;
/* Parse standard arguments */
rv = SSL_CONF_cmd_argv(cctx, &nargs, &args);
if (rv == -3) {
fprintf(stderr, "Missing argument for %s\n", *args);
goto err;
}
if (rv < 0) {
fprintf(stderr, "Error in command %s\n", *args);
ERR_print_errors_fp(stderr);
goto err;
}
/* If rv > 0 we processed something so proceed to next arg */
if (rv > 0)
continue;
/* Otherwise application specific argument processing */
if (strcmp(*args, "-port") == 0) {
port = args[1];
if (port == NULL) {
fprintf(stderr, "Missing -port argument\n");
goto err;
}
args += 2;
nargs -= 2;
continue;
} else {
fprintf(stderr, "Unknown argument %s\n", *args);
goto err;
}
}
if (!SSL_CONF_CTX_finish(cctx)) {
fprintf(stderr, "Finish error\n");
ERR_print_errors_fp(stderr);
goto err;
}
#ifdef ITERATE_CERTS
/*
* Demo of how to iterate over all certificates in an SSL_CTX structure.
*/
{
X509 *x;
int rv;
rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST);
while (rv) {
X509 *x = SSL_CTX_get0_certificate(ctx);
X509_NAME_print_ex_fp(stdout, X509_get_subject_name(x), 0,
XN_FLAG_ONELINE);
printf("\n");
rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT);
}
fflush(stdout);
}
#endif
/* Setup server side SSL bio */
ssl_bio = BIO_new_ssl(ctx, 0);
if ((in = BIO_new_accept(port)) == NULL)
goto err;
/*
* This means that when a new connection is accepted on 'in', The ssl_bio
* will be 'duplicated' and have the new socket BIO push into it.
* Basically it means the SSL BIO will be automatically setup
*/
BIO_set_accept_bios(in, ssl_bio);
again:
/*
* The first call will setup the accept socket, and the second will get a
* socket. In this loop, the first actual accept will occur in the
* BIO_read() function.
*/
if (BIO_do_accept(in) <= 0)
goto err;
for (;;) {
i = BIO_read(in, buf, 512);
if (i == 0) {
/*
* If we have finished, remove the underlying BIO stack so the
* next time we call any function for this BIO, it will attempt
* to do an accept
*/
printf("Done\n");
tmp = BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i < 0)
goto err;
fwrite(buf, 1, i, stdout);
fflush(stdout);
}
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
BIO_free(in);
return ret;
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* A minimal TLS server it ses SSL_CTX_config and a configuration file to
* set most server parameters.
*/
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>
int main(int argc, char *argv[])
{
unsigned char buf[512];
char *port = "*:4433";
BIO *in = NULL;
BIO *ssl_bio, *tmp;
SSL_CTX *ctx;
int ret = EXIT_FAILURE, i;
ctx = SSL_CTX_new(TLS_server_method());
if (CONF_modules_load_file("cmod.cnf", "testapp", 0) <= 0) {
fprintf(stderr, "Error processing config file\n");
goto err;
}
if (SSL_CTX_config(ctx, "server") == 0) {
fprintf(stderr, "Error configuring server.\n");
goto err;
}
/* Setup server side SSL bio */
ssl_bio = BIO_new_ssl(ctx, 0);
if ((in = BIO_new_accept(port)) == NULL)
goto err;
/*
* This means that when a new connection is accepted on 'in', The ssl_bio
* will be 'duplicated' and have the new socket BIO push into it.
* Basically it means the SSL BIO will be automatically setup
*/
BIO_set_accept_bios(in, ssl_bio);
again:
/*
* The first call will setup the accept socket, and the second will get a
* socket. In this loop, the first actual accept will occur in the
* BIO_read() function.
*/
if (BIO_do_accept(in) <= 0)
goto err;
for (;;) {
i = BIO_read(in, buf, sizeof(buf));
if (i == 0) {
/*
* If we have finished, remove the underlying BIO stack so the
* next time we call any function for this BIO, it will attempt
* to do an accept
*/
printf("Done\n");
tmp = BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i < 0) {
if (BIO_should_retry(in))
continue;
goto err;
}
fwrite(buf, 1, i, stdout);
fflush(stdout);
}
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
BIO_free(in);
return ret;
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* A minimal program to serve an SSL connection. It uses blocking. It uses
* the SSL_CONF API with a configuration file. cc -I../../include saccept.c
* -L../.. -lssl -lcrypto -ldl
*/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>
int main(int argc, char *argv[])
{
char *port = "*:4433";
BIO *in = NULL;
BIO *ssl_bio, *tmp;
SSL_CTX *ctx;
SSL_CONF_CTX *cctx = NULL;
CONF *conf = NULL;
STACK_OF(CONF_VALUE) *sect = NULL;
CONF_VALUE *cnf;
long errline = -1;
char buf[512];
int ret = EXIT_FAILURE, i;
ctx = SSL_CTX_new(TLS_server_method());
conf = NCONF_new(NULL);
if (NCONF_load(conf, "accept.cnf", &errline) <= 0) {
if (errline <= 0)
fprintf(stderr, "Error processing config file\n");
else
fprintf(stderr, "Error on line %ld\n", errline);
goto err;
}
sect = NCONF_get_section(conf, "default");
if (sect == NULL) {
fprintf(stderr, "Error retrieving default section\n");
goto err;
}
cctx = SSL_CONF_CTX_new();
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
int rv;
cnf = sk_CONF_VALUE_value(sect, i);
rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value);
if (rv > 0)
continue;
if (rv != -2) {
fprintf(stderr, "Error processing %s = %s\n",
cnf->name, cnf->value);
ERR_print_errors_fp(stderr);
goto err;
}
if (strcmp(cnf->name, "Port") == 0) {
port = cnf->value;
} else {
fprintf(stderr, "Unknown configuration option %s\n", cnf->name);
goto err;
}
}
if (!SSL_CONF_CTX_finish(cctx)) {
fprintf(stderr, "Finish error\n");
ERR_print_errors_fp(stderr);
goto err;
}
/* Setup server side SSL bio */
ssl_bio = BIO_new_ssl(ctx, 0);
if ((in = BIO_new_accept(port)) == NULL)
goto err;
/*
* This means that when a new connection is accepted on 'in', The ssl_bio
* will be 'duplicated' and have the new socket BIO push into it.
* Basically it means the SSL BIO will be automatically setup
*/
BIO_set_accept_bios(in, ssl_bio);
again:
/*
* The first call will setup the accept socket, and the second will get a
* socket. In this loop, the first actual accept will occur in the
* BIO_read() function.
*/
if (BIO_do_accept(in) <= 0)
goto err;
for (;;) {
i = BIO_read(in, buf, 512);
if (i == 0) {
/*
* If we have finished, remove the underlying BIO stack so the
* next time we call any function for this BIO, it will attempt
* to do an accept
*/
printf("Done\n");
tmp = BIO_pop(in);
BIO_free_all(tmp);
goto again;
}
if (i < 0) {
if (BIO_should_retry(in))
continue;
goto err;
}
fwrite(buf, 1, i, stdout);
fflush(stdout);
}
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
BIO_free(in);
return ret;
}

View File

@@ -0,0 +1,17 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgsoKOpzTm/+VR5xOk
kgwtljzMFYtX4NGdqCkxjitXvLmhRANCAASsxTC21z8mDYAX/RgLK5XGJNmPlHcY
VMql6fSeS+9fTZnn1Ma12932/UBfFTITOuHviJYkQ5KxVSitmgMwnF3V
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIBvjCCAWSgAwIBAgIURVOfyUojPPQMfDEVhKY4DIdeLY0wCgYIKoZIzj0EAwIw
NTEfMB0GA1UECwwWVGVzdCBFQ0RTQSBDZXJ0aWZpY2F0ZTESMBAGA1UEAwwJbG9j
YWxob3N0MCAXDTE4MDYxNDEyNDYyOFoYDzIxMTgwNjE0MTI0NjI4WjA1MR8wHQYD
VQQLDBZUZXN0IEVDRFNBIENlcnRpZmljYXRlMRIwEAYDVQQDDAlsb2NhbGhvc3Qw
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASsxTC21z8mDYAX/RgLK5XGJNmPlHcY
VMql6fSeS+9fTZnn1Ma12932/UBfFTITOuHviJYkQ5KxVSitmgMwnF3Vo1AwTjAd
BgNVHQ4EFgQUA0dWehTLHzBYhzfXiTIVUOXDusMwHwYDVR0jBBgwFoAUA0dWehTL
HzBYhzfXiTIVUOXDusMwDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEA
8/l8RyihzqlEnLjcyIEaXTZm4HyNgZRQKhNACCW3jd4CIEbMJAf/D0eY38EeP2xY
/BDy/BYXYmyDQeqiE+RDjG5X
-----END CERTIFICATE-----

View File

@@ -0,0 +1,79 @@
subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert
issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA
-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIIcsOElVeHzfYwDQYJKoZIhvcNAQELBQAwcDELMAkGA1UE
BhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNU
SU5HIFBVUlBPU0VTIE9OTFkxJTAjBgNVBAMMHE9wZW5TU0wgVGVzdCBJbnRlcm1l
ZGlhdGUgQ0EwIBcNMTgwNjE0MTI0NjI4WhgPMjExODA2MTQxMjQ2MjhaMGQxCzAJ
BgNVBAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1Ig
VEVTVElORyBQVVJQT1NFUyBPTkxZMRkwFwYDVQQDDBBUZXN0IFNlcnZlciBDZXJ0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0jIZ8IZ4dIzBc+ZfdmG5
n8G3JzRX99QvIqv52s4hFVfdzoa+AciKJpo9zkegWPmfsAVNa4uVceg/ZQt6qJsu
G/pxbQSZVnyjDQGtt7rgaDEbyUP0XJCnzyRdWSUjFS8yNZn4NkmZU01GlHtXdzWy
dEa5PaiTIwW0HI+bjjOEhwJ1hFuFqzlKHVKHA6DBzNcl6ly0E/q2kyslbR+0hq7p
NMqKvvuAxqgc//W8KvLDlKAt9D3t5zgh2+BrMPemrzjEaM97yHTogJo7+SKVDdUw
YQ7Br3xfyki9u2bUYib1BMSvLezxNP0qf/iU91z4xyLmMvOXE6W0D1WHwya1CfE7
vwIDAQABo3gwdjAdBgNVHQ4EFgQU3ulCbvgfxej6rHnddMpBidwnLIIwHwYDVR0j
BBgwFoAUCgNEpWg658NdblSLsvg43EA1WwUwCQYDVR0TBAIwADATBgNVHSUEDDAK
BggrBgEFBQcDATAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQAD
ggEBAENMzaqJtmWED++W4KXFVwNBkQ87errBXe4jVeYKpjNb0JGMm60MS5ty54fb
r27SsR2EEk3EK2rcd85RR7TEKZCn9SvPykVtVf0tru7nOptQJgSbRvxIzyyq1UcE
K+BXDgN/I0f1X6qbk4Stb6uJF7yyAUabacjwKqgVifOOeKF9WJhVA8qJKoVq7HLN
k+uvm0geO1I4LKeULXVnQy8kwB6twcxN8iPyO45ZxbYIVeEKaYtbj/XPoq6KsLIb
5fj+mK1r/LkWk352ksNhf73r3alF8TBcSLqnbMoy1/ZvzlI4ksp9IGWtIU+CzP/f
VUjh00NOwDLd5jJbPoWW0oNp9m4=
-----END CERTIFICATE-----
subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA
issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Root CA
-----BEGIN CERTIFICATE-----
MIIEPzCCAqegAwIBAgIILsaQqJAjK4IwDQYJKoZIhvcNAQELBQAwaDELMAkGA1UE
BhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBURVNU
SU5HIFBVUlBPU0VTIE9OTFkxHTAbBgNVBAMMFE9wZW5TU0wgVGVzdCBSb290IENB
MCAXDTE4MDYxNDEyNDYyOFoYDzIxMTgwNjE0MTI0NjI4WjBwMQswCQYDVQQGEwJV
SzEWMBQGA1UECgwNT3BlblNTTCBHcm91cDEiMCAGA1UECwwZRk9SIFRFU1RJTkcg
UFVSUE9TRVMgT05MWTElMCMGA1UEAwwcT3BlblNTTCBUZXN0IEludGVybWVkaWF0
ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANIpVng2wNFJp2kF
oJ6Yji25wy1YufnS8NxA82fk5OHdhGWj1CWqnQNotEqEQzcOUszQYrNxd8tEvoWk
Ik4JMBVoEcgBGedchftptTNulFWodWpi1yFaqA/Nz2BsVgcCJW4C+UWDT7VeHtGU
7tYKKr35lxp6io/a4jUDQXvO2nJA9YlrxOktunMqtoZSYqUz35ZXsdkn58o8Fbqm
dEpw6AqAr9aBgY5DSaGxbaX2lwNt9NvB+f9ucOqEnPP8AfTlPYc/ENwJ6u/H8RGw
d1im71mu2lHjcws3aHkbluH860U3vlKWx6Ff1qdQcH98e2HwElqxCK00xya8leu4
u64nljkCAwEAAaNjMGEwHQYDVR0OBBYEFAoDRKVoOufDXW5Ui7L4ONxANVsFMB8G
A1UdIwQYMBaAFDZjTeLsQUG6KL9xuLhzXVdB4pkKMA8GA1UdEwEB/wQFMAMBAf8w
DgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBgQDZQJLA90ewVaS3E3du
gSjPkQ1xsHm8H1am+7zr5oZ81J+R8XYIZgMR+9ShVo38OradiYNqDLso+4iuVdxh
hzoSoQELoDXCficzWKnlAtWvwDDoczyK+/p94g3VKx14n2+GvQzoZ4kwQQgaFH1w
YI6w0oH9zwoklCxvihj8D069QrYyuTT8JGZ2m0FHqVJg6teuQKFahSgwYR2CUoIb
6PrpSUQeCVCH8TPkzlRT6UgtM3ERt7+TlQ+zZ80dSf4YTAsDv9Z/CJXiF/5wZr6/
lWuFjWmX2HkpEW6Wiv5KF8QP6Ft7Z+RYua7RMtELCYvqYbWDBs7fXWGBkZ5xhB09
jCxz+F7zOeRbyzacfFq9DhxCWCRbIrdgGGE/Of2ujJtmK/2p4M6E5IsKNAI2SJBW
iJXvIgQgR22ehPqy6er2Gog5LkWUwqB0kHZJJpbp1IW01IGTpD6YAJyVCEAlyMbo
Kto9+wQFLT3Auv/W5h6OwxkNdfAyZBYy0ZSFk4EE8OdWWY4=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA0jIZ8IZ4dIzBc+ZfdmG5n8G3JzRX99QvIqv52s4hFVfdzoa+
AciKJpo9zkegWPmfsAVNa4uVceg/ZQt6qJsuG/pxbQSZVnyjDQGtt7rgaDEbyUP0
XJCnzyRdWSUjFS8yNZn4NkmZU01GlHtXdzWydEa5PaiTIwW0HI+bjjOEhwJ1hFuF
qzlKHVKHA6DBzNcl6ly0E/q2kyslbR+0hq7pNMqKvvuAxqgc//W8KvLDlKAt9D3t
5zgh2+BrMPemrzjEaM97yHTogJo7+SKVDdUwYQ7Br3xfyki9u2bUYib1BMSvLezx
NP0qf/iU91z4xyLmMvOXE6W0D1WHwya1CfE7vwIDAQABAoIBAQC2HAo1RYvfDoQc
sh9LJWf5bZANO2Brqz4bP/x9AdHP+AyH/l1oliJ7R2785TmbXMppam6lGo4j3h/u
n39pzOip/NWAqldfgySRBD9Jy3LZUpLMUT/JYtrAsLTfozk+BWHu5rMR9boNXgok
Yqho8/DkpNGhBghUc4CUricLkL7laD3ziAHpx8yALL3tnLGOpgT9hNrA8Dm3yfUS
JEfiG12ILXvq1IP+vUNuaLpTLJZuqUmLpK8v+CBYgKxfd+TDnEjul4PqhhIIFK3A
xEZYQR2D/AXUwng9hP9uCbVm5lOY6vRbi9Fpbt+KRv+m25s1AnuhJFBOsL30h/Tb
iCKWm/nhAoGBAO0bFqMvZHjaT2KiwOwG/Ze9NsjynFPVltiuCqNj8HE5wM6imC5J
SdB+jMkgN6ERXALWrtr8Uf2pqzfeMsi6pekOOVTWLe/8c4bAZRxaCZn/BlZRysZI
vB9Gb7m7Oymw5iDSqrYywgOiUu+oIiCrmPOealhmn7zmHzHaETvdL9zDAoGBAOLy
DVT1csoexnuHVIWqnp7FK7lv6eOGZSdXpfJ3XYjmKJLK2hpVZe+J/mFOL1wsKSt4
0k/V0dnkHR7V4Pa4ECiCthkWMWrBVIHe7+ZnZ0ocKQSC+EEecavOiZ57S/qnUlT6
NtQP4cSy4DHzzFZdTZnn+2oymapPZpb2mvSN/GVVAoGADrIlHwwq8Aqn7Pclefuc
8DC8GoxfABs29EslQadKGdp4htYxFH1aY9/UHgsvJ36J82sW/1+wPUas5BOTljlr
WxyUlRuJUVyWVH3MRouWGMNjwynipZOQhWe6OQrPye+688Ha7twKhmsjNNN4+glo
u4DQGpaRxAWHXXGkq88zzj0CgYEAsICEceD7R8srnwMfb13FQ8IhQXWSuAvcO/7k
53CCZGhsgc4WVoi4YNY360G9f7gwxMiQ+NpY/Vd2dnbtIbUBjCAss9IY2OhHa0IR
3mXpZTAFjqa1oR+mVHKrgYBvFSBw3fpEDiXT9wEPcIomD709D0fmty9nZ5edOCfP
WAfdlokCgYEAqXuMuAg3NMMgEv+eBfsf43v3hRwBqPYanE26wcO3GoT/S8BpB6wy
vBoPZOlO5ZfsD2jaTec60GLay+MofxC7qNXIjzHOw50ry4bqHqqoQbn2cONE1k+0
ov7H2keTcG9FEGgL7dRUq3pRUo/W12WmRuDN17IEgkzAeisJnoiPtaQ=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,2 @@
OSSL$LIBSSL_SHR/SHARE
OSSL$LIBCRYPTO_SHR/SHARE

View File

@@ -0,0 +1,2 @@
OSSL$LIBSSL/LIB
OSSL$LIBCRYPTO/LIB

View File

@@ -0,0 +1,24 @@
SUBDIRS=bio cipher digest keyexch mac kdf pkey signature \
encrypt encode sslecho
IF[{- !$disabled{"h3demo"} -}]
IF[{- !$disabled{"quic"} -}]
SUBDIRS=http3
ENDIF
ENDIF
IF[{- !$disabled{"cms"} -}]
IF[{- !$disabled{"deprecated"} -}]
SUBDIRS=cms
ENDIF
ENDIF
IF[{- !$disabled{"dgram"} -}]
SUBDIRS=guide
ENDIF
IF[{- !$disabled{"des"} -}]
IF[{- !$disabled{"deprecated"} -}]
SUBDIRS=smime
ENDIF
ENDIF

View File

@@ -0,0 +1,18 @@
There is often a need to generate test certificates automatically using
a script. This is often a cause for confusion which can result in incorrect
CA certificates, obsolete V1 certificates or duplicate serial numbers.
The range of command line options can be daunting for a beginner.
The mkcerts.sh script is an example of how to generate certificates
automatically using scripts. Example creates a root CA, an intermediate CA
signed by the root and several certificates signed by the intermediate CA.
The script then creates an empty index.txt file and adds entries for the
certificates and generates a CRL. Then one certificate is revoked and a
second CRL generated.
The script ocsprun.sh runs the test responder on port 8888 covering the
client certificates.
The script ocspquery.sh queries the status of the certificates using the
test responder.

View File

@@ -0,0 +1,66 @@
#
# OpenSSL configuration file to create apps directory certificates
#
# This definition stops the following lines choking if HOME or CN
# is undefined.
HOME = .
CN = "Not Defined"
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
####################################################################
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
# Don't prompt for fields: use those in section directly
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = UK
organizationName = OpenSSL Group
organizationalUnitName = FOR TESTING PURPOSES ONLY
# Take CN from environment so it can come from a script.
commonName = $ENV::CN
[ usr_cert ]
# These extensions are added when 'ca' signs a request for an end entity
# certificate
basicConstraints=critical, CA:FALSE
keyUsage=critical, nonRepudiation, digitalSignature, keyEncipherment
[ ec_cert ]
# These extensions are added when 'ca' signs a request for an end entity
# certificate
basicConstraints=critical, CA:FALSE
keyUsage=critical, nonRepudiation, digitalSignature, keyAgreement
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always
basicConstraints = critical,CA:true
keyUsage = critical, cRLSign, keyCertSign

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAtK2p2x0S3C1ajftAc3GaWPsji6scw1k9Sw/XltbLQuDc11/f
wwrUiFcje2CB3Ri6yD6+uCA3V12jEc4GdqzirJZhwgIhaTv42vfYBgiUcR9McEGr
agFC3yVR3lIbOzhBjmXNp1on46irxnzU4pT+w58IuvYqUBavaEtfRZocFR5NsIOy
mRhyNag8htOFK3wmTEYrb0vflFYT6SD47ogYtsd/xWSKS+YFyb7xSusR2Ot6Ktmr
MswQE57QYJz+KiRVlnL0cduMBdT52Wm8blaC9mz50PyrzjQ68NyHapCoWDU7pe4x
HLtzpXGSDMPuw4miiSwMym/2wReYJv6cFugLPQIDAQABAoIBAAZOyc9MhIwLSU4L
p4RgQvM4UVVe8/Id+3XTZ8NsXExJbWxXfIhiqGjaIfL8u4vsgRjcl+v1s/jo2/iT
KMab4o4D8gXD7UavQVDjtjb/ta79WL3SjRl2Uc9YjjMkyq6WmDNQeo2NKDdafCTB
1uzSJtLNipB8Z53ELPuHJhxX9QMHrMnuha49riQgXZ7buP9iQrHJFhImBjSzbxJx
L+TI6rkyLSf9Wi0Pd3L27Ob3QWNfNRYNSeTE+08eSRChkur5W0RuXAcuAICdQlCl
LBvWO/LmmvbzCqiDcgy/TliSb6CGGwgiNG7LJZmlkYNj8laGwalNlYZs3UrVv6NO
Br2loAECgYEA2kvCvPGj0Dg/6g7WhXDvAkEbcaL1tSeCxBbNH+6HS2UWMWvyTtCn
/bbD519QIdkvayy1QjEf32GV/UjUVmlULMLBcDy0DGjtL3+XpIhLKWDNxN1v1/ai
1oz23ZJCOgnk6K4qtFtlRS1XtynjA+rBetvYvLP9SKeFrnpzCgaA2r0CgYEA0+KX
1ACXDTNH5ySX3kMjSS9xdINf+OOw4CvPHFwbtc9aqk2HePlEsBTz5I/W3rKwXva3
NqZ/bRqVVeZB/hHKFywgdUQk2Uc5z/S7Lw70/w1HubNTXGU06Ngb6zOFAo/o/TwZ
zTP1BMIKSOB6PAZPS3l+aLO4FRIRotfFhgRHOoECgYEAmiZbqt8cJaJDB/5YYDzC
mp3tSk6gIb936Q6M5VqkMYp9pIKsxhk0N8aDCnTU+kIK6SzWBpr3/d9Ecmqmfyq7
5SvWO3KyVf0WWK9KH0abhOm2BKm2HBQvI0DB5u8sUx2/hsvOnjPYDISbZ11t0MtK
u35Zy89yMYcSsIYJjG/ROCUCgYEAgI2P9G5PNxEP5OtMwOsW84Y3Xat/hPAQFlI+
HES+AzbFGWJkeT8zL2nm95tVkFP1sggZ7Kxjz3w7cpx7GX0NkbWSE9O+T51pNASV
tN1sQ3p5M+/a+cnlqgfEGJVvc7iAcXQPa3LEi5h2yPR49QYXAgG6cifn3dDSpmwn
SUI7PQECgYEApGCIIpSRPLAEHTGmP87RBL1smurhwmy2s/pghkvUkWehtxg0sGHh
kuaqDWcskogv+QC0sVdytiLSz8G0DwcEcsHK1Fkyb8A+ayiw6jWJDo2m9+IF4Fww
1Te6jFPYDESnbhq7+TLGgHGhtwcu5cnb4vSuYXGXKupZGzoLOBbv1Zw=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAsErw75CmLYD6pkrGW/YhAl/K8L5wJYxDjqu2FghxjD8K308W
3EHq4uBxEwR1OHXaM1+6ZZw7/r2I37VLIdurBEAIEUdbzx0so74FPawgz5EW2CTq
oJnK8F71/vo5Kj1VPwW46CxwxUR3cfvJGNXND2ip0TcyTSPLROXOyQakcVfIGJmd
Sa1wHKi+c2gMA4emADudZUOYLrg80gr2ldePm07ynbVsKKzCcStw8MdmoW9Qt3fL
nPJn2TFUUBNWj+4kvL+88edWCVQXKNdsysD/CDrH4W/hjyPDStVsM6XpiNU0+L2Z
Y6fcj3OP8d0goOx45xotMn9m8hNkCGsrVXx9IwIDAQABAoIBACg3wIV2o2KIJSZg
sqXyHY+0GNEZMO5v9E2NAMo//N941lshaN6wrww5FbK39qH9yNylfxmFLe6sgJhA
fLZprbcXgH+onto+Fpv4UqvCI+4WdHa03U3sJ+70SvxzSy1Gtrbc8FUPJl7qgrFf
Nn5S8CgOwYb4J6KPguTh5G3Z9RPiCKObwOwEM34hrZUlgPS88wmzu9H6L2GM8A1v
YBtEr0msBnlJBJOgStyUEfHW2KspNQ+VllQ6c0cedgFXUpl9EoKTLxP+WXwFI1sx
jFCFzSrMqPcPz1PxU6bXoZE0WH6r+3c8WAW4xR/HVu04BrBDu0CGwn6zAXDy6wCU
pWogDlkCgYEA4o+nIu2CTzqUlgc22pj+hjenfS5lnCtJfAdrXOJHmnuL+J9h8Nzz
9kkL+/Y0Xg9bOM6xXPm+81UNpDvOLbUahSSQsfB+LNVEkthJIL4XIk083LsHjFaJ
9SiCFRbf2OgWrEhe/c1drySwz9u/0f4Q7B6VGqxMnTDjzS5JacZ1pE8CgYEAxzMn
/n/Dpdn+c4rf14BRNKCv1qBXngPNylKJCmiRpKRJAn+B+Msdwtggk/1Ihju21wSo
IGy0Gw7WQd1Iq7V85cB2G5PAFY6ybpSV6G3QrzmzuvjHmKvXgUAuuaN+7Pp1YkMY
rLVjUOcdP5JbXG6XnaCkHYJR8uapPwWPkDt+oO0CgYBI4yZGGlr92j7LNW70TJw1
2dnMcAzIfTSa7lgf/bxDetPBHKWJs8vYxA9S9BZM3Gvgjr6IxuAjsI0+9O6TzdvG
UckrNc+h5Mq241ZDbmRK6MZXzOPUxlKDyJBw8Hb7dU82BeJpjJRDMG6hsHS5vh77
l6sodZ4ARCZFcEq1+N8ICQKBgDeBHJLAXO6YmFrvhkGQ4o+senJuSRuhabUHXGIH
ExXyJNnKV5fQWOGSwTkbKRsmBmNRS9uFDoY/kxnVI8ucjUmjYAV9HNek5DkFs+OI
vc4lYNwnN85li23bSWm2kcZMX2ra0URGYn8HdtHg4Q4XTq3ANhp21oi9FsmVrhP9
T+JdAoGBAK2ebwZ7CXFavDFo4mzLKkGitBjrSi/udFhZECXZWEbNzWlVc3Y3q0cU
drDqUtbVm+/Xb5CMU044Gqq6SKdObAb3JElKmFylFL9fp2rfL/foUr2sdb87Vqdp
2j5jZyvt1DKnNaJ7JaFbUdRxlvHQRiqKlZpafN/SMQ0jCs1bSgCg
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,49 @@
#!/bin/sh
# Recreate the demo certificates in the apps directory.
opensslcmd() {
LD_LIBRARY_PATH=../../.. ../../../apps/openssl $@
}
opensslcmd version
# Root CA: create certificate directly
CN="OpenSSL Test Root CA" opensslcmd req -config apps.cnf -x509 -nodes \
-keyout root.pem -out root.pem -key rootkey.pem -new -days 3650
# Intermediate CA: request first
CN="OpenSSL Test Intermediate CA" opensslcmd req -config apps.cnf -nodes \
-key intkey.pem -out intreq.pem -new
# Sign request: CA extensions
opensslcmd x509 -req -in intreq.pem -CA root.pem -CAkey rootkey.pem -days 3630 \
-extfile apps.cnf -extensions v3_ca -CAcreateserial -out intca.pem
# Client certificate: request first
CN="Test Client Cert" opensslcmd req -config apps.cnf -nodes \
-key ckey.pem -out creq.pem -new
# Sign using intermediate CA
opensslcmd x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile apps.cnf -extensions usr_cert -CAcreateserial | \
opensslcmd x509 -nameopt oneline -subject -issuer >client.pem
# Server certificate: request first
CN="Test Server Cert" opensslcmd req -config apps.cnf -nodes \
-key skey.pem -out sreq.pem -new
# Sign using intermediate CA
opensslcmd x509 -req -in sreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile apps.cnf -extensions usr_cert -CAcreateserial | \
opensslcmd x509 -nameopt oneline -subject -issuer >server.pem
# Server certificate #2: request first
CN="Test Server Cert #2" opensslcmd req -config apps.cnf -nodes \
-key skey2.pem -out sreq2.pem -new
# Sign using intermediate CA
opensslcmd x509 -req -in sreq2.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile apps.cnf -extensions usr_cert -CAcreateserial | \
opensslcmd x509 -nameopt oneline -subject -issuer >server2.pem
# Append keys to file.
cat skey.pem >>server.pem
cat skey2.pem >>server2.pem
cat ckey.pem >>client.pem
opensslcmd verify -CAfile root.pem -untrusted intca.pem \
server2.pem server.pem client.pem

View File

@@ -0,0 +1,35 @@
#!/bin/sh
# Create certificates using various algorithms to test multi-certificate
# functionality.
opensslcmd() {
LD_LIBRARY_PATH=../../.. ../../../apps/openssl $@
}
opensslcmd version
CN="OpenSSL Test RSA SHA-1 cert" opensslcmd req \
-config apps.cnf -extensions usr_cert -x509 -nodes \
-keyout tsha1.pem -out tsha1.pem -new -days 3650 -sha1
CN="OpenSSL Test RSA SHA-256 cert" opensslcmd req \
-config apps.cnf -extensions usr_cert -x509 -nodes \
-keyout tsha256.pem -out tsha256.pem -new -days 3650 -sha256
CN="OpenSSL Test RSA SHA-512 cert" opensslcmd req \
-config apps.cnf -extensions usr_cert -x509 -nodes \
-keyout tsha512.pem -out tsha512.pem -new -days 3650 -sha512
# Create EC parameters
opensslcmd ecparam -name P-256 -out ecp256.pem
opensslcmd ecparam -name P-384 -out ecp384.pem
CN="OpenSSL Test P-256 SHA-256 cert" opensslcmd req \
-config apps.cnf -extensions ec_cert -x509 -nodes \
-nodes -keyout tecp256.pem -out tecp256.pem -newkey ec:ecp256.pem \
-days 3650 -sha256
CN="OpenSSL Test P-384 SHA-384 cert" opensslcmd req \
-config apps.cnf -extensions ec_cert -x509 -nodes \
-nodes -keyout tecp384.pem -out tecp384.pem -newkey ec:ecp384.pem \
-days 3650 -sha384

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEA0xpquKAoY6trkxz8uuE6RyYfMOy+Rgvt19pqG3x8sEpFNjDN
IG873HniShNaOrseRtrGRgCDcecNOQ0LLOQYo10zz0er8+0YgUWVx5Ag5q3cqN3T
kjDc+0sRZMONPoUwD0ySOT9dumbJypEjA0q2AgKgWwaO4ilzg/fWTEruLeuL4meX
K9WZFmMnGuF4kHSocZeKWs5UM86WIOf/+NdtzLNd6a5HwqAB5Azggiz2Ngck6Aet
Mi0inBr3A1MSn0oIaQ7rGvbQ2QrIOnpdHJ36GadQHuvvtZOm28o8UVONMMWoS1yJ
/1TaRWQJ+faZJE7yegJtUf75+5HwsxaUP32C3wIDAQABAoIBAQCEybEnwVamm0Vn
nGw9AT+vUYN9Ou3VEdviUzk7YOrt2Un/9GKTbGSzItf80H+JQfqhhywBDIGiPDxN
Dq9g5Xm6CP51/BdlsFYhuqukhDyt3d9XOXHEG4hlaarfP0KxeQXqGbhA2mMSxWVZ
TkI/59blHNHRcCagjIJlGJhsFRYNO1/ApfA5zN7fWCFvH1XWZhuvsPDgUXKm4BS0
p3ol67MVJHRfYcLb/txBO5rBhSXinK0jEBiljRcE0rWzRycSedmDgG3SNV17wvA0
UWgMNpPcJ1b7Satr0nM7A8+siV8FRcfvPqCuGPKCYTrNn71hGJEhKXKwlURj9+95
O5yzRxjBAoGBAPtTRYN40/piRB0XLpi+zNh+4Ba4TGfXSymbaozgC/pI5wfgGXrz
IpT9ujjV42r8TABHvXa6uiGm0cbxcUgq2n6Y8rf6iHxmn23ezCEBUs7rd6jtt11b
m58T8o0XWyOgAovaH0UgzMtrlsZYR2fli5254oRkTWwaUTuO38z6CVddAoGBANcH
nvdu3RniIYStsr5/deu7l81ZQ9rSiR1m3H6Wy8ryMIfkYfa0WqXhwNHrLrhvhLIQ
7mGnJ+jAkJyVQULE6UdbmVW8tC58Dfrgz/1s7RMeUYPnOmRpx79c/LqZ2IunfFWx
IvBvFu7vidEHA+1tU2N+oXNsU+B9XpfsJ+/d2QtrAoGBAJTuP58tFtClMp/agO5b
AqC4bqqIBB704cGCK53XlsF2OhHcprzJH5ES2iub8+wOHit8V7Xn6SzP4jf2E58k
Zd3nXM3RVNgDKC6/fE+CrUOZHYupcqOMCag29eDOGl/+DgQ5+ZXJXhKdaveWkJns
2NNat/SkS4zn+4NDozOgZ7CxAoGBAIuXjfJRTUXNUDci0APtGO9U1AJiLbOzs4Gb
0g539IqmWS0O7S3L/YDsolFkXOsssjcq2KYabsUhpX+RQVGIJWzGoS9QlqQKssSo
Bz4c5Xbg2shHZtfi9+JaClNVJofazdOPcAAoDfpFFPHWnQ0YSOcxQLx+maEFok/7
5h1IputLAoGBAKGBWDPwskgRRfCAIFpCJLOu/9D30M/akMtO0kJYQpBjOaKuigUy
ic7pthFVse/pMUljXHAd1hs2CTjMW1ukEusU3x1Ei6wvnHHqn0Hs+6D5NQFQkcMn
7rejJ+bpJPRAn40AAV5hGBYI12XycB8ZgyPC4hTUK6unGVK06DC4qvdv
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA84TzkjbcskbKZnrlKcXzSSgi07n+4N7kOM7uIhzpkTuU0HIv
h4VZS2axxfV6hV3CD9MuKVg2zEhroqK1Js5n4ke230nSP/qiELfCl0R+hzRtbfKL
tFUr1iHeU0uQ6v3q+Tg1K/Tmmg72uxKrhyHDL7z0BriPjhAHJ5XlQsvR1RCMkqzu
D9wjSInJxpMMIgLndOclAKv4D1wQtYU7ZpTw+01XBlUhIiXb86qpYL9NqnnRq5JI
uhmOEuxo2ca63+xaHNhD/udSyc8C0Md/yX6wlONTRFgLLv0pdLUGm1xEjfsydaQ6
qGd7hzIKUI3hohNKJa/mHLElv7SZolPTogK/EQIDAQABAoIBAADq9FwNtuE5IRQn
zGtO4q7Y5uCzZ8GDNYr9RKp+P2cbuWDbvVAecYq2NV9QoIiWJOAYZKklOvekIju3
r0UZLA0PRiIrTg6NrESx3JrjWDK8QNlUO7CPTZ39/K+FrmMkV9lem9yxjJjyC34D
AQB+YRTx+l14HppjdxNwHjAVQpIx/uO2F5xAMuk32+3K+pq9CZUtrofe1q4Agj9R
5s8mSy9pbRo9kW9wl5xdEotz1LivFOEiqPUJTUq5J5PeMKao3vdK726XI4Z455Nm
W2/MA0YV0ug2FYinHcZdvKM6dimH8GLfa3X8xKRfzjGjTiMSwsdjgMa4awY3tEHH
674jhAECgYEA/zqMrc0zsbNk83sjgaYIug5kzEpN4ic020rSZsmQxSCerJTgNhmg
utKSCt0Re09Jt3LqG48msahX8ycqDsHNvlEGPQSbMu9IYeO3Wr3fAm75GEtFWePY
BhM73I7gkRt4s8bUiUepMG/wY45c5tRF23xi8foReHFFe9MDzh8fJFECgYEA9EFX
4qAik1pOJGNei9BMwmx0I0gfVEIgu0tzeVqT45vcxbxr7RkTEaDoAG6PlbWP6D9a
WQNLp4gsgRM90ZXOJ4up5DsAWDluvaF4/omabMA+MJJ5kGZ0gCj5rbZbKqUws7x8
bp+6iBfUPJUbcqNqFmi/08Yt7vrDnMnyMw2A/sECgYEAiiuRMxnuzVm34hQcsbhH
6ymVqf7j0PW2qK0F4H1ocT9qhzWFd+RB3kHWrCjnqODQoI6GbGr/4JepHUpre1ex
4UEN5oSS3G0ru0rC3U4C59dZ5KwDHFm7ffZ1pr52ljfQDUsrjjIMRtuiwNK2OoRa
WSsqiaL+SDzSB+nBmpnAizECgYBdt/y6rerWUx4MhDwwtTnel7JwHyo2MDFS6/5g
n8qC2Lj6/fMDRE22w+CA2esp7EJNQJGv+b27iFpbJEDh+/Lf5YzIT4MwVskQ5bYB
JFcmRxUVmf4e09D7o705U/DjCgMH09iCsbLmqQ38ONIRSHZaJtMDtNTHD1yi+jF+
OT43gQKBgQC/2OHZoko6iRlNOAQ/tMVFNq7fL81GivoQ9F1U0Qr+DH3ZfaH8eIkX
xT0ToMPJUzWAn8pZv0snA0um6SIgvkCuxO84OkANCVbttzXImIsL7pFzfcwV/ERK
UM6j0ZuSMFOCr/lGPAoOQU0fskidGEHi1/kW+suSr28TqsyYZpwBDQ==
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA63Yu4/cnLRvi+BIwcoIz5hKmcziREG2tujKEBs4JVO3uV3+f
UW/4YFULigKImXu/0fKyuMyeFu4l3V8NC6gachvAeWhiniN9sPgPU3AQKaF1y9gq
2EBEI2cFCKS5WASItjZCY951ZKuXYJdYDgC4kPlvI4N5M4ORHPa4pqfa/dzfMLEi
92sLGn7q5mArzn+5Xh2jD9Vif8w0RlDRxv1rQ413PGVBtfuhF1PSXNhbPtjpn+33
DdJdNACv8D4PDmjUtKyshqvSXSE/RURldW13v68efBWhOQiLXcAkmISbxfzveS1k
KMSV8nuWwhS5rw0xMlavRTEgqbX7Jm14xGRrFwIDAQABAoIBAHLsTPihIfLnYIE5
x4GsQQ5zXeBw5ITDM37ktwHnQDC+rIzyUl1aLD1AZRBoKinXd4lOTqLZ4/NHKx4A
DYr58mZtWyUmqLOMmQVuHXTZBlp7XtYuXMMNovQwjQlp9LicBeoBU6gQ5PVMtubD
F4xGF89Sn0cTHW3iMkqTtQ5KcR1j57OcJO0FEb1vPvk2MXI5ZyAatUYE7YacbEzd
rg02uIwx3FqNSkuSI79uz4hMdV5TPtuhxx9nTwj9aLUhXFeZ0mn2PVgVzEnnMoJb
+znlsZDgzDlJqdaD744YGWh8Z3OEssB35KfzFcdOeO6yH8lmv2Zfznk7pNPT7LTb
Lae9VgkCgYEA92p1qnAB3NtJtNcaW53i0S5WJgS1hxWKvUDx3lTB9s8X9fHpqL1a
E94fDfWzp/hax6FefUKIvBOukPLQ6bYjTMiFoOHzVirghAIuIUoMI5VtLhwD1hKs
Lr7l/dptMgKb1nZHyXoKHRBthsy3K4+udsPi8TzMvYElgEqyQIe/Rk0CgYEA86GL
8HC6zLszzKERDPBxrboRmoFvVUCTQDhsfj1M8aR3nQ8V5LkdIJc7Wqm/Ggfk9QRf
rJ8M2WUMlU5CNnCn/KCrKzCNZIReze3fV+HnKdbcXGLvgbHPrhnz8yYehUFG+RGq
bVyDWRU94T38izy2s5qMYrMJWZEYyXncSPbfcPMCgYAtaXfxcZ+V5xYPQFARMtiX
5nZfggvDoJuXgx0h3tK/N2HBfcaSdzbaYLG4gTmZggc/jwnl2dl5E++9oSPhUdIG
3ONSFUbxsOsGr9PBvnKd8WZZyUCXAVRjPBzAzF+whzQNWCZy/5htnz9LN7YDI9s0
5113Q96cheDZPFydZY0hHQKBgQDVbEhNukM5xCiNcu+f2SaMnLp9EjQ4h5g3IvaP
5B16daw/Dw8LzcohWboqIxeAsze0GD/D1ZUJAEd0qBjC3g+a9BjefervCjKOzXng
38mEUm+6EwVjJSQcjSmycEs+Sr/kwr/8i5WYvU32+jk4tFgMoC+o6tQe/Uesf68k
z/dPVwKBgGbF7Vv1/3SmhlOy+zYyvJ0CrWtKxH9QP6tLIEgEpd8x7YTSuCH94yok
kToMXYA3sWNPt22GbRDZ+rcp4c7HkDx6I6vpdP9aQEwJTp0EPy0sgWr2XwYmreIQ
NFmkk8Itn9EY2R9VBaP7GLv5kvwxDdLAnmwGmzVtbmaVdxCaBwUk
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,82 @@
#
# OpenSSL example configuration file for automated certificate creation.
#
# This definition stops the following lines choking if HOME or CN
# is undefined.
HOME = .
CN = "Not Defined"
default_ca = ca
# Comment out the next line to ignore configuration errors
config_diagnostics = 1
####################################################################
[ req ]
default_bits = 1024
default_keyfile = privkey.pem
# Don't prompt for fields: use those in section directly
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only
# req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = UK
organizationName = OpenSSL Group
# Take CN from environment so it can come from a script.
commonName = $ENV::CN
[ usr_cert ]
# These extensions are added when 'ca' signs a request for an end entity
# certificate
basicConstraints=critical, CA:FALSE
keyUsage=critical, nonRepudiation, digitalSignature, keyEncipherment
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
# OCSP responder certificate
[ ocsp_cert ]
basicConstraints=critical, CA:FALSE
keyUsage=critical, nonRepudiation, digitalSignature, keyEncipherment
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
extendedKeyUsage=OCSPSigning
[ dh_cert ]
# These extensions are added when 'ca' signs a request for an end entity
# DH certificate
basicConstraints=critical, CA:FALSE
keyUsage=critical, keyAgreement
# PKIX recommendations harmless if included in all certificates.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid
[ v3_ca ]
# Extensions for a typical CA
# PKIX recommendation.
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always
basicConstraints = critical,CA:true
keyUsage = critical, cRLSign, keyCertSign
# Minimal CA entry to allow generation of CRLs.
[ca]
database=index.txt
crlnumber=crlnum.txt

View File

@@ -0,0 +1,101 @@
#!/bin/sh
opensslcmd() {
LD_LIBRARY_PATH=../.. ../../apps/openssl $@
}
OPENSSL_CONF=../../apps/openssl.cnf
export OPENSSL_CONF
opensslcmd version
# Root CA: create certificate directly
CN="Test Root CA" opensslcmd req -config ca.cnf -x509 -nodes \
-keyout root.pem -out root.pem -newkey rsa:2048 -days 3650
# Intermediate CA: request first
CN="Test Intermediate CA" opensslcmd req -config ca.cnf -nodes \
-keyout intkey.pem -out intreq.pem -newkey rsa:2048
# Sign request: CA extensions
opensslcmd x509 -req -in intreq.pem -CA root.pem -days 3600 \
-extfile ca.cnf -extensions v3_ca -CAcreateserial -out intca.pem
# Server certificate: create request first
CN="Test Server Cert" opensslcmd req -config ca.cnf -nodes \
-keyout skey.pem -out req.pem -newkey rsa:1024
# Sign request: end entity extensions
opensslcmd x509 -req -in req.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile ca.cnf -extensions usr_cert -CAcreateserial -out server.pem
# Client certificate: request first
CN="Test Client Cert" opensslcmd req -config ca.cnf -nodes \
-keyout ckey.pem -out creq.pem -newkey rsa:1024
# Sign using intermediate CA
opensslcmd x509 -req -in creq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile ca.cnf -extensions usr_cert -CAcreateserial -out client.pem
# Revoked certificate: request first
CN="Test Revoked Cert" opensslcmd req -config ca.cnf -nodes \
-keyout revkey.pem -out rreq.pem -newkey rsa:1024
# Sign using intermediate CA
opensslcmd x509 -req -in rreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile ca.cnf -extensions usr_cert -CAcreateserial -out rev.pem
# OCSP responder certificate: request first
CN="Test OCSP Responder Cert" opensslcmd req -config ca.cnf -nodes \
-keyout respkey.pem -out respreq.pem -newkey rsa:1024
# Sign using intermediate CA and responder extensions
opensslcmd x509 -req -in respreq.pem -CA intca.pem -CAkey intkey.pem -days 3600 \
-extfile ca.cnf -extensions ocsp_cert -CAcreateserial -out resp.pem
# Example creating a PKCS#3 DH certificate.
# First DH parameters
[ -f dhp.pem ] || opensslcmd genpkey -genparam -algorithm DH -pkeyopt dh_paramgen_prime_len:1024 -out dhp.pem
# Now a DH private key
opensslcmd genpkey -paramfile dhp.pem -out dhskey.pem
# Create DH public key file
opensslcmd pkey -in dhskey.pem -pubout -out dhspub.pem
# Certificate request, key just reuses old one as it is ignored when the
# request is signed.
CN="Test Server DH Cert" opensslcmd req -config ca.cnf -new \
-key skey.pem -out dhsreq.pem
# Sign request: end entity DH extensions
opensslcmd x509 -req -in dhsreq.pem -CA root.pem -days 3600 \
-force_pubkey dhspub.pem \
-extfile ca.cnf -extensions dh_cert -CAcreateserial -out dhserver.pem
# DH client certificate
opensslcmd genpkey -paramfile dhp.pem -out dhckey.pem
opensslcmd pkey -in dhckey.pem -pubout -out dhcpub.pem
CN="Test Client DH Cert" opensslcmd req -config ca.cnf -new \
-key skey.pem -out dhcreq.pem
opensslcmd x509 -req -in dhcreq.pem -CA root.pem -days 3600 \
-force_pubkey dhcpub.pem \
-extfile ca.cnf -extensions dh_cert -CAcreateserial -out dhclient.pem
# Examples of CRL generation without the need to use 'ca' to issue
# certificates.
# Create zero length index file
>index.txt
# Create initial crl number file
echo 01 >crlnum.txt
# Add entries for server and client certs
opensslcmd ca -valid server.pem -keyfile root.pem -cert root.pem \
-config ca.cnf -md sha1
opensslcmd ca -valid client.pem -keyfile root.pem -cert root.pem \
-config ca.cnf -md sha1
opensslcmd ca -valid rev.pem -keyfile root.pem -cert root.pem \
-config ca.cnf -md sha1
# Generate a CRL.
opensslcmd ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \
-md sha1 -crldays 1 -out crl1.pem
# Revoke a certificate
openssl ca -revoke rev.pem -crl_reason superseded \
-keyfile root.pem -cert root.pem -config ca.cnf -md sha1
# Generate another CRL
opensslcmd ca -gencrl -keyfile root.pem -cert root.pem -config ca.cnf \
-md sha1 -crldays 1 -out crl2.pem

View File

@@ -0,0 +1,28 @@
#!/bin/sh
# Example querying OpenSSL test responder. Assumes ocsprun.sh has been
# called.
opensslcmd() {
LD_LIBRARY_PATH=../.. ../../apps/openssl $@
}
OPENSSL_CONF=../../apps/openssl.cnf
export OPENSSL_CONF
opensslcmd version
# Send responder queries for each certificate.
echo "Requesting OCSP status for each certificate"
opensslcmd ocsp -issuer intca.pem -cert client.pem -CAfile root.pem \
-url http://127.0.0.1:8888/
opensslcmd ocsp -issuer intca.pem -cert server.pem -CAfile root.pem \
-url http://127.0.0.1:8888/
opensslcmd ocsp -issuer intca.pem -cert rev.pem -CAfile root.pem \
-url http://127.0.0.1:8888/
# One query for all three certificates.
echo "Requesting OCSP status for three certificates in one request"
opensslcmd ocsp -issuer intca.pem \
-cert client.pem -cert server.pem -cert rev.pem \
-CAfile root.pem -url http://127.0.0.1:8888/

View File

@@ -0,0 +1,21 @@
#!/bin/sh
opensslcmd() {
LD_LIBRARY_PATH=../.. ../../apps/openssl $@
}
# Example of running an querying OpenSSL test OCSP responder.
# This assumes "mkcerts.sh" or similar has been run to set up the
# necessary file structure.
OPENSSL_CONF=../../apps/openssl.cnf
export OPENSSL_CONF
opensslcmd version
# Run OCSP responder.
PORT=8888
opensslcmd ocsp -port $PORT -index index.txt -CA intca.pem \
-rsigner resp.pem -rkey respkey.pem -rother intca.pem $*

View File

@@ -0,0 +1,35 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./aesccm
TESTS = aesccm \
aesgcm \
aeskeywrap \
ariacbc
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
aesccm: aesccm.o
aesgcm: aesgcm.o
aeskeywrap: aeskeywrap.o
ariacbc: ariacbc.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) $(TESTS) *.o
.PHONY: test
test: all
@echo "\nCipher tests:"
@set -e; for tst in $(TESTS); do \
echo "\n"$$tst; \
LD_LIBRARY_PATH=../.. ./$$tst; \
done

View File

@@ -0,0 +1,238 @@
/*
* Copyright 2013-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Simple AES CCM authenticated encryption with additional data (AEAD)
* demonstration program.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
/* AES-CCM test data obtained from NIST public test vectors */
/* AES key */
static const unsigned char ccm_key[] = {
0xce, 0xb0, 0x09, 0xae, 0xa4, 0x45, 0x44, 0x51, 0xfe, 0xad, 0xf0, 0xe6,
0xb3, 0x6f, 0x45, 0x55, 0x5d, 0xd0, 0x47, 0x23, 0xba, 0xa4, 0x48, 0xe8
};
/* Unique nonce to be used for this message */
static const unsigned char ccm_nonce[] = {
0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7
};
/*
* Example of Additional Authenticated Data (AAD), i.e. unencrypted data
* which can be authenticated using the generated Tag value.
*/
static const unsigned char ccm_adata[] = {
0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, 0xc9, 0xab, 0x25, 0xc7,
0x5f, 0x10, 0xbd, 0xe7, 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5,
0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4
};
/* Example plaintext to encrypt */
static const unsigned char ccm_pt[] = {
0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, 0xe6, 0x9c, 0x2a, 0x1f,
0x58, 0x93, 0x9d, 0xfe, 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10
};
/* Expected ciphertext value */
static const unsigned char ccm_ct[] = {
0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, 0x87, 0xfd, 0x95, 0xa2,
0x8a, 0xd3, 0x92, 0xc8, 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd
};
/* Expected AEAD Tag value */
static const unsigned char ccm_tag[] = {
0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, 0x23, 0xdc, 0x07, 0x44,
0x14, 0xdb, 0x50, 0x6d
};
/*
* A library context and property query can be used to select & filter
* algorithm implementations. If they are NULL then the default library
* context and properties are used.
*/
static OSSL_LIB_CTX *libctx = NULL;
static const char *propq = NULL;
static int aes_ccm_encrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
size_t ccm_nonce_len = sizeof(ccm_nonce);
size_t ccm_tag_len = sizeof(ccm_tag);
unsigned char outbuf[1024];
unsigned char outtag[16];
OSSL_PARAM params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES CCM Encrypt:\n");
printf("Plaintext:\n");
BIO_dump_fp(stdout, ccm_pt, sizeof(ccm_pt));
/* Create a context for the encrypt operation */
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-192-CCM", propq)) == NULL)
goto err;
/* Default nonce length for AES-CCM is 7 bytes (56 bits). */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&ccm_nonce_len);
/* Set tag length */
params[1] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
NULL, ccm_tag_len);
/*
* Initialise encrypt operation with the cipher & mode,
* nonce length and tag length parameters.
*/
if (!EVP_EncryptInit_ex2(ctx, cipher, NULL, NULL, params))
goto err;
/* Initialise key and nonce */
if (!EVP_EncryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce))
goto err;
/* Set plaintext length: only needed if AAD is used */
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_pt)))
goto err;
/* Zero or one call to specify any AAD */
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)))
goto err;
/* Encrypt plaintext: can only be called once */
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, ccm_pt, sizeof(ccm_pt)))
goto err;
/* Output encrypted block */
printf("Ciphertext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Finalise: note get no output for CCM */
if (!EVP_EncryptFinal_ex(ctx, NULL, &tmplen))
goto err;
/* Get tag */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
outtag, ccm_tag_len);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_CIPHER_CTX_get_params(ctx, params))
goto err;
/* Output tag */
printf("Tag:\n");
BIO_dump_fp(stdout, outtag, ccm_tag_len);
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aes_ccm_decrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, rv;
unsigned char outbuf[1024];
size_t ccm_nonce_len = sizeof(ccm_nonce);
OSSL_PARAM params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES CCM Decrypt:\n");
printf("Ciphertext:\n");
BIO_dump_fp(stdout, ccm_ct, sizeof(ccm_ct));
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-192-CCM", propq)) == NULL)
goto err;
/* Set nonce length if default 96 bits is not appropriate */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&ccm_nonce_len);
/* Set tag length */
params[1] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
(unsigned char *)ccm_tag,
sizeof(ccm_tag));
/*
* Initialise decrypt operation with the cipher & mode,
* nonce length and expected tag parameters.
*/
if (!EVP_DecryptInit_ex2(ctx, cipher, NULL, NULL, params))
goto err;
/* Specify key and IV */
if (!EVP_DecryptInit_ex(ctx, NULL, NULL, ccm_key, ccm_nonce))
goto err;
/* Set ciphertext length: only needed if we have AAD */
if (!EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, sizeof(ccm_ct)))
goto err;
/* Zero or one call to specify any AAD */
if (!EVP_DecryptUpdate(ctx, NULL, &outlen, ccm_adata, sizeof(ccm_adata)))
goto err;
/* Decrypt plaintext, verify tag: can only be called once */
rv = EVP_DecryptUpdate(ctx, outbuf, &outlen, ccm_ct, sizeof(ccm_ct));
/* Output decrypted block: if tag verify failed we get nothing */
if (rv > 0) {
printf("Tag verify successful!\nPlaintext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
} else {
printf("Tag verify failed!\nPlaintext not available\n");
goto err;
}
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int main(int argc, char **argv)
{
if (!aes_ccm_encrypt())
return EXIT_FAILURE;
if (!aes_ccm_decrypt())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright 2012-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Simple AES GCM authenticated encryption with additional data (AEAD)
* demonstration program.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
/* AES-GCM test data obtained from NIST public test vectors */
/* AES key */
static const unsigned char gcm_key[] = {
0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};
/* Unique initialisation vector */
static const unsigned char gcm_iv[] = {
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};
/* Example plaintext to encrypt */
static const unsigned char gcm_pt[] = {
0xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e, 0xeb, 0x31, 0xb2, 0xea,
0xcc, 0x2b, 0xf2, 0xa5
};
/*
* Example of Additional Authenticated Data (AAD), i.e. unencrypted data
* which can be authenticated using the generated Tag value.
*/
static const unsigned char gcm_aad[] = {
0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43,
0x7f, 0xec, 0x78, 0xde
};
/* Expected ciphertext value */
static const unsigned char gcm_ct[] = {
0xf7, 0x26, 0x44, 0x13, 0xa8, 0x4c, 0x0e, 0x7c, 0xd5, 0x36, 0x86, 0x7e,
0xb9, 0xf2, 0x17, 0x36
};
/* Expected AEAD Tag value */
static const unsigned char gcm_tag[] = {
0x67, 0xba, 0x05, 0x10, 0x26, 0x2a, 0xe4, 0x87, 0xd7, 0x37, 0xee, 0x62,
0x98, 0xf7, 0x7e, 0x0c
};
/*
* A library context and property query can be used to select & filter
* algorithm implementations. If they are NULL then the default library
* context and properties are used.
*/
static OSSL_LIB_CTX *libctx = NULL;
static const char *propq = NULL;
static int aes_gcm_encrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
size_t gcm_ivlen = sizeof(gcm_iv);
unsigned char outbuf[1024];
unsigned char outtag[16];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES GCM Encrypt:\n");
printf("Plaintext:\n");
BIO_dump_fp(stdout, gcm_pt, sizeof(gcm_pt));
/* Create a context for the encrypt operation */
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq)) == NULL)
goto err;
/* Set IV length if default 96 bits is not appropriate */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&gcm_ivlen);
/*
* Initialise an encrypt operation with the cipher/mode, key, IV and
* IV length parameter.
* For demonstration purposes the IV is being set here. In a compliant
* application the IV would be generated internally so the iv passed in
* would be NULL.
*/
if (!EVP_EncryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
goto err;
/* Zero or more calls to specify any AAD */
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)))
goto err;
/* Encrypt plaintext */
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, gcm_pt, sizeof(gcm_pt)))
goto err;
/* Output encrypted block */
printf("Ciphertext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Finalise: note get no output for GCM */
if (!EVP_EncryptFinal_ex(ctx, outbuf, &tmplen))
goto err;
/* Get tag */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
outtag, 16);
if (!EVP_CIPHER_CTX_get_params(ctx, params))
goto err;
/* Output tag */
printf("Tag:\n");
BIO_dump_fp(stdout, outtag, 16);
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aes_gcm_decrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, rv;
size_t gcm_ivlen = sizeof(gcm_iv);
unsigned char outbuf[1024];
OSSL_PARAM params[2] = {
OSSL_PARAM_END, OSSL_PARAM_END
};
printf("AES GCM Decrypt:\n");
printf("Ciphertext:\n");
BIO_dump_fp(stdout, gcm_ct, sizeof(gcm_ct));
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-GCM", propq)) == NULL)
goto err;
/* Set IV length if default 96 bits is not appropriate */
params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN,
&gcm_ivlen);
/*
* Initialise an encrypt operation with the cipher/mode, key, IV and
* IV length parameter.
*/
if (!EVP_DecryptInit_ex2(ctx, cipher, gcm_key, gcm_iv, params))
goto err;
/* Zero or more calls to specify any AAD */
if (!EVP_DecryptUpdate(ctx, NULL, &outlen, gcm_aad, sizeof(gcm_aad)))
goto err;
/* Decrypt plaintext */
if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, gcm_ct, sizeof(gcm_ct)))
goto err;
/* Output decrypted block */
printf("Plaintext:\n");
BIO_dump_fp(stdout, outbuf, outlen);
/* Set expected tag value. */
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
(void*)gcm_tag, sizeof(gcm_tag));
if (!EVP_CIPHER_CTX_set_params(ctx, params))
goto err;
/* Finalise: note get no output for GCM */
rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
/*
* Print out return value. If this is not successful authentication
* failed and plaintext is not trustworthy.
*/
printf("Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int main(int argc, char **argv)
{
if (!aes_gcm_encrypt())
return EXIT_FAILURE;
if (!aes_gcm_decrypt())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,180 @@
/*
* Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Simple aes wrap encryption demonstration program.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/core_names.h>
/* aes key */
static const unsigned char wrap_key[] = {
0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};
/* Unique initialisation vector */
static const unsigned char wrap_iv[] = {
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84,
0x99, 0xaa, 0x3e, 0x68,
};
/* Example plaintext to encrypt */
static const unsigned char wrap_pt[] = {
0xad, 0x4f, 0xc9, 0xfc, 0x77, 0x69, 0xc9, 0xea, 0xfc, 0xdf, 0x00, 0xac,
0x34, 0xec, 0x40, 0xbc, 0x28, 0x3f, 0xa4, 0x5e, 0xd8, 0x99, 0xe4, 0x5d,
0x5e, 0x7a, 0xc4, 0xe6, 0xca, 0x7b, 0xa5, 0xb7,
};
/* Expected ciphertext value */
static const unsigned char wrap_ct[] = {
0x97, 0x99, 0x55, 0xca, 0xf6, 0x3e, 0x95, 0x54, 0x39, 0xd6, 0xaf, 0x63, 0xff, 0x2c, 0xe3, 0x96,
0xf7, 0x0d, 0x2c, 0x9c, 0xc7, 0x43, 0xc0, 0xb6, 0x31, 0x43, 0xb9, 0x20, 0xac, 0x6b, 0xd3, 0x67,
0xad, 0x01, 0xaf, 0xa7, 0x32, 0x74, 0x26, 0x92,
};
/*
* A library context and property query can be used to select & filter
* algorithm implementations. If they are NULL then the default library
* context and properties are used.
*/
static OSSL_LIB_CTX *libctx = NULL;
static const char *propq = NULL;
static int aes_wrap_encrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
printf("aes wrap Encrypt:\n");
printf("Plaintext:\n");
BIO_dump_fp(stdout, wrap_pt, sizeof(wrap_pt));
/* Create a context for the encrypt operation */
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-WRAP", propq)) == NULL)
goto err;
/*
* Initialise an encrypt operation with the cipher/mode, key and IV.
* We are not setting any custom params so let params be just NULL.
*/
if (!EVP_EncryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL))
goto err;
/* Encrypt plaintext */
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, wrap_pt, sizeof(wrap_pt)))
goto err;
/* Finalise: there can be some additional output from padding */
if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))
goto err;
outlen += tmplen;
/* Output encrypted block */
printf("Ciphertext (outlen:%d):\n", outlen);
BIO_dump_fp(stdout, outbuf, outlen);
if (sizeof(wrap_ct) == outlen && !CRYPTO_memcmp(outbuf, wrap_ct, outlen))
printf("Final ciphertext matches expected ciphertext\n");
else
printf("Final ciphertext differs from expected ciphertext\n");
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aes_wrap_decrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
printf("aes wrap Decrypt:\n");
printf("Ciphertext:\n");
BIO_dump_fp(stdout, wrap_ct, sizeof(wrap_ct));
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "aes-256-wrap", propq)) == NULL)
goto err;
/*
* Initialise an encrypt operation with the cipher/mode, key and IV.
* We are not setting any custom params so let params be just NULL.
*/
if (!EVP_DecryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL))
goto err;
/* Decrypt plaintext */
if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, wrap_ct, sizeof(wrap_ct)))
goto err;
/* Finalise: there can be some additional output from padding */
if (!EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))
goto err;
outlen += tmplen;
/* Output decrypted block */
printf("Plaintext (outlen:%d):\n", outlen);
BIO_dump_fp(stdout, outbuf, outlen);
if (sizeof(wrap_pt) == outlen && !CRYPTO_memcmp(outbuf, wrap_pt, outlen))
printf("Final plaintext matches original plaintext\n");
else
printf("Final plaintext differs from original plaintext\n");
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int main(int argc, char **argv)
{
if (!aes_wrap_encrypt())
return EXIT_FAILURE;
if (!aes_wrap_decrypt())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,175 @@
/*
* Copyright 2012-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Simple ARIA CBC encryption demonstration program.
*/
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/crypto.h>
#include <openssl/core_names.h>
/* ARIA key */
static const unsigned char cbc_key[] = {
0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};
/* Unique initialisation vector */
static const unsigned char cbc_iv[] = {
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84,
0x99, 0xaa, 0x3e, 0x68,
};
/* Example plaintext to encrypt */
static const unsigned char cbc_pt[] = {
0xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e, 0xeb, 0x31, 0xb2, 0xea,
0xcc, 0x2b, 0xf2, 0xa5
};
/* Expected ciphertext value */
static const unsigned char cbc_ct[] = {
0x9a, 0x44, 0xe6, 0x85, 0x94, 0x26, 0xff, 0x30, 0x03, 0xd3, 0x7e, 0xc6,
0xb5, 0x4a, 0x09, 0x66, 0x39, 0x28, 0xf3, 0x67, 0x14, 0xbc, 0xe8, 0xe2,
0xcf, 0x31, 0xb8, 0x60, 0x42, 0x72, 0x6d, 0xc8
};
/*
* A library context and property query can be used to select & filter
* algorithm implementations. If they are NULL then the default library
* context and properties are used.
*/
static OSSL_LIB_CTX *libctx = NULL;
static const char *propq = NULL;
static int aria_cbc_encrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
printf("ARIA CBC Encrypt:\n");
printf("Plaintext:\n");
BIO_dump_fp(stdout, cbc_pt, sizeof(cbc_pt));
/* Create a context for the encrypt operation */
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "ARIA-256-CBC", propq)) == NULL)
goto err;
/*
* Initialise an encrypt operation with the cipher/mode, key and IV.
* We are not setting any custom params so let params be just NULL.
*/
if (!EVP_EncryptInit_ex2(ctx, cipher, cbc_key, cbc_iv, /* params */ NULL))
goto err;
/* Encrypt plaintext */
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, cbc_pt, sizeof(cbc_pt)))
goto err;
/* Finalise: there can be some additional output from padding */
if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))
goto err;
outlen += tmplen;
/* Output encrypted block */
printf("Ciphertext (outlen:%d):\n", outlen);
BIO_dump_fp(stdout, outbuf, outlen);
if (sizeof(cbc_ct) == outlen && !CRYPTO_memcmp(outbuf, cbc_ct, outlen))
printf("Final ciphertext matches expected ciphertext\n");
else
printf("Final ciphertext differs from expected ciphertext\n");
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
static int aria_cbc_decrypt(void)
{
int ret = 0;
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher = NULL;
int outlen, tmplen;
unsigned char outbuf[1024];
printf("ARIA CBC Decrypt:\n");
printf("Ciphertext:\n");
BIO_dump_fp(stdout, cbc_ct, sizeof(cbc_ct));
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
goto err;
/* Fetch the cipher implementation */
if ((cipher = EVP_CIPHER_fetch(libctx, "ARIA-256-CBC", propq)) == NULL)
goto err;
/*
* Initialise an encrypt operation with the cipher/mode, key and IV.
* We are not setting any custom params so let params be just NULL.
*/
if (!EVP_DecryptInit_ex2(ctx, cipher, cbc_key, cbc_iv, /* params */ NULL))
goto err;
/* Decrypt plaintext */
if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, cbc_ct, sizeof(cbc_ct)))
goto err;
/* Finalise: there can be some additional output from padding */
if (!EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen))
goto err;
outlen += tmplen;
/* Output decrypted block */
printf("Plaintext (outlen:%d):\n", outlen);
BIO_dump_fp(stdout, outbuf, outlen);
if (sizeof(cbc_pt) == outlen && !CRYPTO_memcmp(outbuf, cbc_pt, outlen))
printf("Final plaintext matches original plaintext\n");
else
printf("Final plaintext differs from original plaintext\n");
ret = 1;
err:
if (!ret)
ERR_print_errors_fp(stderr);
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
return ret;
}
int main(int argc, char **argv)
{
if (!aria_cbc_encrypt())
return EXIT_FAILURE;
if (!aria_cbc_decrypt())
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,17 @@
PROGRAMS{noinst}=aesccm aesgcm aeskeywrap ariacbc
INCLUDE[aesccm]=../../include
SOURCE[aesccm]=aesccm.c
DEPEND[aesccm]=../../libcrypto ../../libssl
INCLUDE[aesgcm]=../../include
SOURCE[aesgcm]=aesgcm.c
DEPEND[aesgcm]=../../libcrypto ../../libssl
INCLUDE[aeskeywrap]=../../include
SOURCE[aeskeywrap]=aeskeywrap.c
DEPEND[aeskeywrap]=../../libcrypto ../../libssl
INCLUDE[ariacbc]=../../include
SOURCE[ariacbc]=ariacbc.c
DEPEND[ariacbc]=../../libcrypto ../../libssl

View File

@@ -0,0 +1,45 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto is on the library path. For example, to run the
# cms_enc demo:
#
# LD_LIBRARY_PATH=../.. ./cms_enc
TESTS = cms_comp \
cms_ddec \
cms_dec \
cms_denc \
cms_enc \
cms_sign \
cms_sign2 \
cms_uncomp \
cms_ver
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
cms_comp: cms_comp.o
cms_ddec: cms_ddec.o
cms_dec: cms_dec.o
cms_denc: cms_denc.o
cms_enc: cms_enc.o
cms_sign: cms_sign.o
cms_sign2: cms_sign2.o
cms_uncomp: cms_uncomp.o
cms_ver: cms_ver.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) $(TESTS) *.o
test: all
@echo "\nCMS tests:"
LD_LIBRARY_PATH=../.. ./cms_enc
LD_LIBRARY_PATH=../.. ./cms_dec
LD_LIBRARY_PATH=../.. ./cms_sign2
LD_LIBRARY_PATH=../.. ./cms_ver

View File

@@ -0,0 +1,45 @@
PROGRAMS{noinst} = cms_comp \
cms_ddec \
cms_dec \
cms_denc \
cms_enc \
cms_sign \
cms_sign2 \
cms_uncomp \
cms_ver
INCLUDE[cms_comp]=../../include
SOURCE[cms_comp]=cms_comp.c
DEPEND[cms_comp]=../../libcrypto ../../libssl
INCLUDE[cms_ddec]=../../include
SOURCE[cms_ddec]=cms_ddec.c
DEPEND[cms_ddec]=../../libcrypto ../../libssl
INCLUDE[cms_dec]=../../include
SOURCE[cms_dec]=cms_dec.c
DEPEND[cms_dec]=../../libcrypto ../../libssl
INCLUDE[cms_denc]=../../include
SOURCE[cms_denc]=cms_denc.c
DEPEND[cms_denc]=../../libcrypto ../../libssl
INCLUDE[cms_enc]=../../include
SOURCE[cms_enc]=cms_enc.c
DEPEND[cms_enc]=../../libcrypto ../../libssl
INCLUDE[cms_sign]=../../include
SOURCE[cms_sign]=cms_sign.c
DEPEND[cms_sign]=../../libcrypto ../../libssl
INCLUDE[cms_sign2]=../../include
SOURCE[cms_sign2]=cms_sign2.c
DEPEND[cms_sign2]=../../libcrypto ../../libssl
INCLUDE[cms_uncomp]=../../include
SOURCE[cms_uncomp]=cms_uncomp.c
DEPEND[cms_uncomp]=../../libcrypto ../../libssl
INCLUDE[cms_ver]=../../include
SOURCE[cms_ver]=cms_ver.c
DEPEND[cms_ver]=../../libcrypto ../../libssl

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFBjCCA26gAwIBAgIUM/WihZJZUTZvqoyNaUlp59DOaWYwDQYJKoZIhvcNAQEL
BQAwVzELMAkGA1UEBhMCVUsxEjAQBgNVBAcMCVRlc3QgQ2l0eTEWMBQGA1UECgwN
T3BlblNTTCBHcm91cDEcMBoGA1UEAwwTVGVzdCBTL01JTUUgUm9vdCBDQTAgFw0x
ODA2MTQxMjQ2MjhaGA8yMTE4MDYxNDEyNDYyOFowVzELMAkGA1UEBhMCVUsxEjAQ
BgNVBAcMCVRlc3QgQ2l0eTEWMBQGA1UECgwNT3BlblNTTCBHcm91cDEcMBoGA1UE
AwwTVGVzdCBTL01JTUUgUm9vdCBDQTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCC
AYoCggGBAMzxOVHZFVxN9XQIVW3y1bK5ir3jKpKkU6zKrw8MdRvm233eqWSOYJvs
3rgdT59iv+CaPcBT5offbP0eH43H96CubJji/vQLMUzc/cLrJuCbLHREbSCsFNpf
lYw5mkT98dCFV66HuN6Nwqi5kW8TxGSXkD4OZqklbbicrXoXh5qhREID5hgbrijy
BiIHyp6bDq5zUCcmHP/Gdw2aTMEQZNsdw4MavtB65vI7dYxo2zEzdmJ3NnjlG7qZ
6Od6V4IW8yRAK9GLj0TUCZl28pq6rNio+F5Lst3clX9PDxh7LphNrXXYiHjXp2Kn
LZbOnz1SJSmCeisy/EFN6fRtwdwqcM1AcKNBU+UqFq0Mv0sgNdRwghYWGQht0mT9
+Pg5HxTzDlOOmBT1kAduxJNLiRQlgysPDN94Os0EpzJyA87Z6yJRGvYGZ5mrdfx2
8p6bHptf46h1WzCX4wDy2J86y+odgWMnSkmF9h8ySj66rgmLrz40n+mDm8bhUblK
AV8IqN8WmQIDAQABo4HHMIHEMB0GA1UdDgQWBBSkmMaBYQPTEGcqe1maU2IDOMLQ
ezCBlAYDVR0jBIGMMIGJgBSkmMaBYQPTEGcqe1maU2IDOMLQe6FbpFkwVzELMAkG
A1UEBhMCVUsxEjAQBgNVBAcMCVRlc3QgQ2l0eTEWMBQGA1UECgwNT3BlblNTTCBH
cm91cDEcMBoGA1UEAwwTVGVzdCBTL01JTUUgUm9vdCBDQYIUM/WihZJZUTZvqoyN
aUlp59DOaWYwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAYEAqP1CQRGM
roHvk6dhI4ElNae5seRdSQNTtwAhlP1RoSoFz8xybMgDksKE07t77gDsKvU2SuXV
fdICqVpjpN9cRYKM6VmiREdU6OGsPQ74u4sOg4cT/tuou0RsD/uQaznb5NOvo2T0
8rmX0Ai3+lbEuMBCaGNU0KYJifYy4QrSqEapq4W3NbqH85msOiKHEDh1vz9IWz6z
WKjdv9lst56XuLTZrJ/O0T0qD6aMXyqK6ZART/FELjDXc+9Ey4TH+msOEKq0uQWt
y7Grfmz52dTnAjBw+6/ggE9sA8Wo6DhwbEUaOA9BB5YP+XWsIkUUbiVHU7D8TyiE
KHt2DkaWvjl1/RdtzQUO/vGI4yuFTZfLf23KcwgtHJI3JxLNAMLM3I2jmoWhKm/d
GkVYsGH1GWonv0UTv/TKlOXaTYWK9fQVoYkFc+FrwUd2lev5FizJNigL9qatGyRZ
giJmWWlf0bMMIxwWZzQswxLyKdkNlvkKf9T6BjEmGLeOHZCn0x2sOyUi
-----END CERTIFICATE-----

View File

@@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG5QIBAAKCAYEAzPE5UdkVXE31dAhVbfLVsrmKveMqkqRTrMqvDwx1G+bbfd6p
ZI5gm+zeuB1Pn2K/4Jo9wFPmh99s/R4fjcf3oK5smOL+9AsxTNz9wusm4JssdERt
IKwU2l+VjDmaRP3x0IVXroe43o3CqLmRbxPEZJeQPg5mqSVtuJyteheHmqFEQgPm
GBuuKPIGIgfKnpsOrnNQJyYc/8Z3DZpMwRBk2x3Dgxq+0Hrm8jt1jGjbMTN2Ync2
eOUbupno53pXghbzJEAr0YuPRNQJmXbymrqs2Kj4Xkuy3dyVf08PGHsumE2tddiI
eNenYqctls6fPVIlKYJ6KzL8QU3p9G3B3CpwzUBwo0FT5SoWrQy/SyA11HCCFhYZ
CG3SZP34+DkfFPMOU46YFPWQB27Ek0uJFCWDKw8M33g6zQSnMnIDztnrIlEa9gZn
mat1/Hbynpsem1/jqHVbMJfjAPLYnzrL6h2BYydKSYX2HzJKPrquCYuvPjSf6YOb
xuFRuUoBXwio3xaZAgMBAAECggGBAJrqILzozke2ujpablEtBTITJHgC9lRgmMt9
bjR+4ysTJ4kOvZbANPDIbVZY+a3uVEIv9UujYBgG4Hi4w3tF074G+xnaRIQuzbZf
OgaUABA527GLY74VtbGYHRAhHqbWGmrX0H6iIzE/kQw/MVr4YzTyiFsQQbPMEhNB
g7RNgvh0vIb2MYC5s71JrS8eGqAnb0KY8daV7ce9upJyt2Acx1AGQJqipegrbtVd
8q4PONkJIIyvtmJONNaprq8DAJDaTNdcZu7f7mymF5UFpp4Lh6raAvOZAZjgkPYW
PsX2uMAsYchXTmSDGOHNafqeyTS0UEaw6FRhpxzMoSxRXX4/RhjeShadYwHxbh7s
UwFU7S9EWlj8CjgGs00KFM1eMV0sEYsL8sRf7ZiWM5XJsmXKbRZjA5V+7OoSGElB
zJcERK6NFCISijApZlVveEVZS0qESivKd9bspOzbMdoJyjBW1LZdMH85YIwM8Dox
VqGR0QD3UP8RpZBRwTiFenqOpwARnQKBwQD1NBGcTxLLUUluEBG/TD9KM5sCnkm8
cn5RomwTeBrUr9SXOJuUPa8RNLrAeosuWCrx9JkF25IBExQbbs1NRHuziOIOyI0+
hvqP85zJln7kUDtiDMFfUdS8Q6PF3b3wJl6cbipowWwsahvUSkx3W8UWrzZHsvrO
LBtvEZdwetNWN50FK040uM6y/x71xfvUhlKBsuZBgDFU9aXJZAGpkCklZnByURN6
LZudDQETdYo7/X8qqPlcHwHStGj9YXg/e38CgcEA1fdVA6s+KlRUGRTUDaUFPDji
MciTcvA3teXJWNAsFWd71oLT5eQNI50afF242ikTT6JuXFH0mMYKoVe/LFo7m2mf
uLcW4yM/FiKTkhnBQGm7KNqyvXB0T0DWTDSeS7hTzD6KjuJPf7JVH5I4In8jSKJd
3mzTA9keIosnxjX7EOsZNQd0+MKaJYHnvJsxYaoT9FXoONuyzQu96TQ8Q+fkVHXh
I/ENAw0qfoJ5mw5dQnU2UtjP6cSNVQ9Rsr48GNnnAoHBAJcI65AMZNc3yrMw0r2y
iYl7IBAMz/5zx7shANE9OcmoRJqhE7PMCvneMOo+kVyKkmlW8KrbBKQEzG3ZYjwl
4sxDlHrmrZnGKrBgrkK9oIuhn/JVSQcdsJwGTeqjG0vBVqWkdhrwiWESOvIYkeEz
dcLzScwAQtyb7ooLm+x8u5Bv0RhOBG4VJ7y5yKg6u1O9KTUarRnLjJd4eBYEs8Fu
Oun+n2TK6+RmE2Q5jmAeFne9PYdZbb+Ame7fkYwBbcAsoQKBwQC1KHQSZyp7LGsH
0Vq5Mr77/i2FeQ1eg4SnvaZ8S8UHWla/iIVgX3XAcYO7SJ76F00CX8SQ5dLyhrr5
YBG8u6k8LHHPMzVtmqoPU7cePDAjGWIddQ1g15WihILsgqCD+8z3YPxvfa1RsOvh
jyt4Ca0WEmLnr7v5xhp9pNRIPewUpvjwrR+cfyeEGjjat4tX5Wh/tzym51y7vvVM
Pa3I0M3BtQyqIa2ip8MS2eWcIs1TN2qHOorOolwHaLEDZY38fIECgcAKns98A2G3
tLvZaDZlVsJWZsdSDUrFCKvx9QbTZHbyOL5JU/8TgLBgfOgV2yxLXn9Pq+0Quvb2
EjaFuA3GKOFi50WtfwR6Yo1DaFcx5n0bDShnaHOF+dUi0BVQd2V1DsqAwF5/Eh3A
lX+XuWeSam4/91WhmNMCZpfYv0GErs4ZBHHsl54jmvrrjbhg/efUvpWKi/9vlKm+
+ITH+nG1xCnyEEVZ+vm9Qq57lCLBZGyGT4PetllpsRrGcdO4/gfK8lY=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME compress example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
/*
* On OpenSSL 1.0.0+ only:
* for streaming set CMS_STREAM
*/
int flags = CMS_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Open content being compressed */
in = BIO_new_file("comp.txt", "r");
if (!in)
goto err;
/* compress content */
cms = CMS_compress(in, NID_zlib_compression, flags);
if (!cms)
goto err;
out = BIO_new_file("smcomp.txt", "w");
if (!out)
goto err;
/* Write out S/MIME message */
if (!SMIME_write_CMS(out, cms, in, flags))
goto err;
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Compressing Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out);
return ret;
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* S/MIME detached data decrypt example: rarely done but should the need
* arise this is an example....
*/
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL, *dcont = NULL;
X509 *rcert = NULL;
EVP_PKEY *rkey = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Read in recipient certificate and private key */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (BIO_reset(tbio) < 0)
goto err;
rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
if (!rcert || !rkey)
goto err;
/* Open PEM file containing enveloped data */
in = BIO_new_file("smencr.pem", "r");
if (!in)
goto err;
/* Parse PEM content */
cms = PEM_read_bio_CMS(in, NULL, 0, NULL);
if (!cms)
goto err;
/* Open file containing detached content */
dcont = BIO_new_file("smencr.out", "rb");
if (!in)
goto err;
out = BIO_new_file("encrout.txt", "w");
if (!out)
goto err;
/* Decrypt S/MIME message */
if (!CMS_decrypt(cms, rkey, rcert, dcont, out, 0))
goto err;
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Decrypting Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(rcert);
EVP_PKEY_free(rkey);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
BIO_free(dcont);
return ret;
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME decryption example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL;
X509 *rcert = NULL;
EVP_PKEY *rkey = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Read in recipient certificate and private key */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (BIO_reset(tbio) < 0)
goto err;
rkey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
if (!rcert || !rkey)
goto err;
/* Open S/MIME message to decrypt */
in = BIO_new_file("smencr.txt", "r");
if (!in)
goto err;
/* Parse message */
cms = SMIME_read_CMS(in, NULL);
if (!cms)
goto err;
out = BIO_new_file("decout.txt", "w");
if (!out)
goto err;
/* Decrypt S/MIME message */
if (!CMS_decrypt(cms, rkey, rcert, NULL, out, 0))
goto err;
printf("Decryption Successful\n");
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Decrypting Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(rcert);
EVP_PKEY_free(rkey);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* S/MIME detached data encrypt example: rarely done but should the need
* arise this is an example....
*/
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL, *dout = NULL;
X509 *rcert = NULL;
STACK_OF(X509) *recips = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
int flags = CMS_STREAM | CMS_DETACHED;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Read in recipient certificate */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (!rcert)
goto err;
/* Create recipient STACK and add recipient cert to it */
recips = sk_X509_new_null();
if (!recips || !sk_X509_push(recips, rcert))
goto err;
/*
* OSSL_STACK_OF_X509_free() free up recipient STACK and its contents
* so set rcert to NULL so it isn't freed up twice.
*/
rcert = NULL;
/* Open content being encrypted */
in = BIO_new_file("encr.txt", "r");
dout = BIO_new_file("smencr.out", "wb");
if (!in)
goto err;
/* encrypt content */
cms = CMS_encrypt(recips, in, EVP_des_ede3_cbc(), flags);
if (!cms)
goto err;
out = BIO_new_file("smencr.pem", "w");
if (!out)
goto err;
if (!CMS_final(cms, in, dout, flags))
goto err;
/* Write out CMS structure without content */
if (!PEM_write_bio_CMS(out, cms))
goto err;
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Encrypting Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(rcert);
OSSL_STACK_OF_X509_free(recips);
BIO_free(in);
BIO_free(out);
BIO_free(dout);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME encrypt example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL;
X509 *rcert = NULL;
STACK_OF(X509) *recips = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
/*
* On OpenSSL 1.0.0 and later only:
* for streaming set CMS_STREAM
*/
int flags = CMS_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Read in recipient certificate */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (!rcert)
goto err;
/* Create recipient STACK and add recipient cert to it */
recips = sk_X509_new_null();
if (!recips || !sk_X509_push(recips, rcert))
goto err;
/*
* OSSL_STACK_OF_X509_free() will free up recipient STACK and its contents
* so set rcert to NULL so it isn't freed up twice.
*/
rcert = NULL;
/* Open content being encrypted */
in = BIO_new_file("encr.txt", "r");
if (!in)
goto err;
/* encrypt content */
cms = CMS_encrypt(recips, in, EVP_des_ede3_cbc(), flags);
if (!cms)
goto err;
out = BIO_new_file("smencr.txt", "w");
if (!out)
goto err;
/* Write out S/MIME message */
if (!SMIME_write_CMS(out, cms, in, flags))
goto err;
printf("Encryption Successful\n");
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Encrypting Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(rcert);
OSSL_STACK_OF_X509_free(recips);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME signing example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL;
X509 *scert = NULL;
EVP_PKEY *skey = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
/*
* For simple S/MIME signing use CMS_DETACHED. On OpenSSL 1.0.0 only: for
* streaming detached set CMS_DETACHED|CMS_STREAM for streaming
* non-detached set CMS_STREAM
*/
int flags = CMS_DETACHED | CMS_STREAM;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Read in signer certificate and private key */
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
scert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (BIO_reset(tbio) < 0)
goto err;
skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
if (!scert || !skey)
goto err;
/* Open content being signed */
in = BIO_new_file("sign.txt", "r");
if (!in)
goto err;
/* Sign content */
cms = CMS_sign(scert, skey, NULL, in, flags);
if (!cms)
goto err;
out = BIO_new_file("smout.txt", "w");
if (!out)
goto err;
if (!(flags & CMS_STREAM)) {
if (BIO_reset(in) < 0)
goto err;
}
/* Write out S/MIME message */
if (!SMIME_write_CMS(out, cms, in, flags))
goto err;
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Signing Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(scert);
EVP_PKEY_free(skey);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* S/MIME signing example: 2 signers */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL;
X509 *scert = NULL, *scert2 = NULL;
EVP_PKEY *skey = NULL, *skey2 = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
tbio = BIO_new_file("signer.pem", "r");
if (!tbio)
goto err;
scert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (BIO_reset(tbio) < 0)
goto err;
skey = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
BIO_free(tbio);
tbio = BIO_new_file("signer2.pem", "r");
if (!tbio)
goto err;
scert2 = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (BIO_reset(tbio) < 0)
goto err;
skey2 = PEM_read_bio_PrivateKey(tbio, NULL, 0, NULL);
if (!scert2 || !skey2)
goto err;
in = BIO_new_file("sign.txt", "r");
if (!in)
goto err;
cms = CMS_sign(NULL, NULL, NULL, in, CMS_STREAM | CMS_PARTIAL);
if (!cms)
goto err;
/* Add each signer in turn */
if (!CMS_add1_signer(cms, scert, skey, NULL, 0))
goto err;
if (!CMS_add1_signer(cms, scert2, skey2, NULL, 0))
goto err;
out = BIO_new_file("smout.txt", "w");
if (!out)
goto err;
/* NB: content included and finalized by SMIME_write_CMS */
if (!SMIME_write_CMS(out, cms, in, CMS_STREAM))
goto err;
printf("Signing Successful\n");
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Signing Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
X509_free(scert);
EVP_PKEY_free(skey);
X509_free(scert2);
EVP_PKEY_free(skey2);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME uncompression example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Open compressed content */
in = BIO_new_file("smcomp.txt", "r");
if (!in)
goto err;
/* Sign content */
cms = SMIME_read_CMS(in, NULL);
if (!cms)
goto err;
out = BIO_new_file("smuncomp.txt", "w");
if (!out)
goto err;
/* Uncompress S/MIME message */
if (!CMS_uncompress(cms, out, NULL, 0))
goto err;
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Uncompressing Data\n");
ERR_print_errors_fp(stderr);
}
CMS_ContentInfo_free(cms);
BIO_free(in);
BIO_free(out);
return ret;
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2008-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Simple S/MIME verification example */
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
/*
* print any signingTime attributes.
* signingTime is when each party purportedly signed the message.
*/
static void print_signingTime(CMS_ContentInfo *cms)
{
STACK_OF(CMS_SignerInfo) *sis;
CMS_SignerInfo *si;
X509_ATTRIBUTE *attr;
ASN1_TYPE *t;
ASN1_UTCTIME *utctime;
ASN1_GENERALIZEDTIME *gtime;
BIO *b;
int i, loc;
b = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
sis = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
si = sk_CMS_SignerInfo_value(sis, i);
loc = CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1);
attr = CMS_signed_get_attr(si, loc);
t = X509_ATTRIBUTE_get0_type(attr, 0);
if (t == NULL)
continue;
switch (t->type) {
case V_ASN1_UTCTIME:
utctime = t->value.utctime;
ASN1_UTCTIME_print(b, utctime);
break;
case V_ASN1_GENERALIZEDTIME:
gtime = t->value.generalizedtime;
ASN1_GENERALIZEDTIME_print(b, gtime);
break;
default:
fprintf(stderr, "unrecognized signingTime type\n");
break;
}
BIO_printf(b, ": signingTime from SignerInfo %i\n", i);
}
BIO_free(b);
return;
}
int main(int argc, char **argv)
{
BIO *in = NULL, *out = NULL, *tbio = NULL, *cont = NULL;
X509_STORE *st = NULL;
X509 *cacert = NULL;
CMS_ContentInfo *cms = NULL;
int ret = EXIT_FAILURE;
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
/* Set up trusted CA certificate store */
st = X509_STORE_new();
if (st == NULL)
goto err;
/* Read in CA certificate */
tbio = BIO_new_file("cacert.pem", "r");
if (tbio == NULL)
goto err;
cacert = PEM_read_bio_X509(tbio, NULL, 0, NULL);
if (cacert == NULL)
goto err;
if (!X509_STORE_add_cert(st, cacert))
goto err;
/* Open message being verified */
in = BIO_new_file("smout.txt", "r");
if (in == NULL)
goto err;
/* parse message */
cms = SMIME_read_CMS(in, &cont);
if (cms == NULL)
goto err;
print_signingTime(cms);
/* File to output verified content to */
out = BIO_new_file("smver.txt", "w");
if (out == NULL)
goto err;
if (!CMS_verify(cms, NULL, st, cont, out, 0)) {
fprintf(stderr, "Verification Failure\n");
goto err;
}
printf("Verification Successful\n");
ret = EXIT_SUCCESS;
err:
if (ret != EXIT_SUCCESS) {
fprintf(stderr, "Error Verifying Data\n");
ERR_print_errors_fp(stderr);
}
X509_STORE_free(st);
CMS_ContentInfo_free(cms);
X509_free(cacert);
BIO_free(in);
BIO_free(out);
BIO_free(tbio);
return ret;
}

View File

@@ -0,0 +1,22 @@
Content-type: text/plain
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed
Some Text To be Compressed

View File

@@ -0,0 +1,3 @@
Content-type: text/plain
Sample OpenSSL Data for CMS encryption

View File

@@ -0,0 +1,3 @@
Content-type: text/plain
Test OpenSSL CMS Signed Content

View File

@@ -0,0 +1,52 @@
-----BEGIN CERTIFICATE-----
MIIELDCCApSgAwIBAgIIcsOElVeHzfQwDQYJKoZIhvcNAQELBQAwVzELMAkGA1UE
BhMCVUsxEjAQBgNVBAcMCVRlc3QgQ2l0eTEWMBQGA1UECgwNT3BlblNTTCBHcm91
cDEcMBoGA1UEAwwTVGVzdCBTL01JTUUgUm9vdCBDQTAgFw0xODA2MTQxMjQ2Mjha
GA8yMTE4MDYxNDEyNDYyOFowVjELMAkGA1UEBhMCVUsxJTAjBgNVBAMMHE9wZW5T
U0wgdGVzdCBTL01JTUUgc2lnbmVyIDExIDAeBgkqhkiG9w0BCQEWEXRlc3QxQG9w
ZW5zc2wub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1vvSgaL1
byi9AE8Ep3v7Yv36JxYywaZhUy8dEFRiYn6NsVhhNo6SK1Mp8daQ0MZoMzbT1aKp
JTLTgDJZHit2t1d6l3aWJG+cbcLua+XKowaZjj6rirB390fuL4qt5PiAb571QFtu
L8apcydwGEdkaPRuCnvctN8VcZPTKh+M8VEESyxk5K37QYKaAB6ItWR5KhjiAuDt
zsJbjEtOvGtmu2FRCU47GzfkdjYo7tY38WTY+2WWh+idKErtmYSinmhE0H7+yoJB
s1VCI+cq5tVW+oEO9HF4vEDEUykEFFPsCEkIWM+RjCgK8cRSCpg6VQr+ZTii6k7C
m9CP81QhUoV3QwIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1P
cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUg1DE7OaNqMQQ
8Z1bvjhnlisxfsMwHwYDVR0jBBgwFoAUpJjGgWED0xBnKntZmlNiAzjC0HswDQYJ
KoZIhvcNAQELBQADggGBAGxAivCwPsAYmMZfVJTELWNNMBzKzmeRvrp6k/6S74Pw
LDEhTnslCV4U1gTSd3nQ+LRm1fkzxLA12A/rlqN51P8B+hyVSMN9dj54YUcFd+KO
XhkSDrSpph6hRqGy8zqELzlb1Q8yoIBclEmyv+CkXMrpnm+4JL4kzyj/iBRkZTDz
ns15jJD9KHgrOnclaoDRkOT6lGbsd3j+aviKEj8ZILufSMw+W2YORy3nSAencjbO
ezivVujqm+pjkfqdCS1HcFB7LhQEILfFqkssw8YmtJVrM9LF8VIcqueXbVZmeS/1
QV5B7OEmtsM+NkoLF5ldWdPQvmftbShh+AAlpcsmqiRefQgA3aQn6YOnOHnnQwgB
oQRNjQXsjgxV4t2HFYpwkK41kx4HToVGciPNMkndzfY/GJmgXsXfB6/AfUfhLTDv
tbws1MZhaCNOffw3/SVS2nLREMFCGn5uAgNkqssWqeWJu3910XF640tqPBj5YGFc
fykwWNhG5xS04EHpztgKdQ==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1vvSgaL1byi9AE8Ep3v7Yv36JxYywaZhUy8dEFRiYn6NsVhh
No6SK1Mp8daQ0MZoMzbT1aKpJTLTgDJZHit2t1d6l3aWJG+cbcLua+XKowaZjj6r
irB390fuL4qt5PiAb571QFtuL8apcydwGEdkaPRuCnvctN8VcZPTKh+M8VEESyxk
5K37QYKaAB6ItWR5KhjiAuDtzsJbjEtOvGtmu2FRCU47GzfkdjYo7tY38WTY+2WW
h+idKErtmYSinmhE0H7+yoJBs1VCI+cq5tVW+oEO9HF4vEDEUykEFFPsCEkIWM+R
jCgK8cRSCpg6VQr+ZTii6k7Cm9CP81QhUoV3QwIDAQABAoIBAQC6LCWmIisNcmgK
RmOvbszKc0sYYj7eOGl8EgbHR2xUA2hNNk4pYtnuLvzZ84hBZDCEeWyFS3HTRuql
z/QhDl6mc1k0pXtsXkNHQlIamksbVvHPnzIKzrt1J5N7FEt3SERhZXTZoNQRB6di
k7qdK+YmhdZtucnt0GrPisaJaf0yU/EjLuX+MU/0Xrc23lVhR3yqYhaOhWvrxTHM
evykI0kOL+gU58eN2eWE4ELjS2z+njKDqcEyeIy00FdBAtCoKjMsWpRytKNmcFm9
LdtMmizskF8VS3+XsDbkseIODx1xJ65IFmHHMV2xLG5/+bQppkB8JuE3EDrtFiUJ
lGdfmBlxAoGBAP3Asg0drdunv7imeEOGpyj5JwF1hCVQ71IBGdqTr3aPqOlDH/io
up7t+VBuSLqj1P20HygNjow+ALw/Ko+a0icodg7QA2Co0/RiBwa+u2SgpYDqC9Kt
KIdRcv+NXkhXF/DLIn0jJvI53OtKsbgTv/C+aCipblofnO9sF4AhShq1AoGBANjj
Ou0czloNORbk3qAxLi4b5P/YOyZBJDa0zijFdD1jImfOeyNFXeg2ID+8ZjDkP/eP
pLy/Gt/8bVb+O+9wMOho3kWKZBN3O2VsLJYakAehDsC5ax7i2HtEqg1L1krW2duS
POiKg3qNjETM30zTA4pHwkNAETIktResze7SRm0XAoGABH7KaLMS5mZFXjcMwF19
TpuDVmJHkgWqB7DfTWD6ZcZLvr4irdwHWlNq7ELX5P6MAmaTerkqwk9C4hLYZSzf
9jOgS8jhlm/HOXgXGcZ9OV4jMHJ0/Sl2I1eNCvvtJKjuUqS2mrLpuLbPtBdhqJoo
91HYNIgz3ULcG921WN6+GlUCgYEA066T6LDgxgt52NpwXrEhfWdETmDg+ilCCxLU
0/5DwVZsUhy5Gmeti+Kn/w0GQFnGBP1xr7ZlqI9auDlSjhNV6L/RkNXNbyJEGm1F
5wrt4ERVfcx6vJ5y43zU7D1EXa7s2t0UDXKDeK2GZe//UZ/yKJh5BeIV5nblOMI0
DA+3JOkCgYEA80QGLjGlCvxKceVbuohbIZ1+/EoXPq993ER9S8D2MTGATsEcygtF
rM8JcHTv75sjycqu68BAQr1Z5qwwrMyY0vWVEorKzvAXEWolC67asR4cDutOd+qy
WlEIyojX45GwHCHpcbVRiGRWuj3kwkc+WzdgusBoAJrPCigES/Cr8uA=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,52 @@
-----BEGIN CERTIFICATE-----
MIIELDCCApSgAwIBAgIIcsOElVeHzfUwDQYJKoZIhvcNAQELBQAwVzELMAkGA1UE
BhMCVUsxEjAQBgNVBAcMCVRlc3QgQ2l0eTEWMBQGA1UECgwNT3BlblNTTCBHcm91
cDEcMBoGA1UEAwwTVGVzdCBTL01JTUUgUm9vdCBDQTAgFw0xODA2MTQxMjQ2Mjha
GA8yMTE4MDYxNDEyNDYyOFowVjELMAkGA1UEBhMCVUsxJTAjBgNVBAMMHE9wZW5T
U0wgdGVzdCBTL01JTUUgc2lnbmVyIDIxIDAeBgkqhkiG9w0BCQEWEXRlc3QyQG9w
ZW5zc2wub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ledrM9R
3x3bZypZAEi00DJYAmLS5F6Gg3+xpjE745UWKrjDAY5KswavKKa3vZxoUz2omNSg
4nYfLSowq7AI3VnZ8LwNo8lAeo7AX9elrsmzQzhr2DCdCdbRhCWoiS/ba5tKIhlb
gFnP+pB8jhC9qZuQJkpVaivywMW8rA9DRbeDcQjDKhUi0ukVDYHDd9+FtNM3H1t3
AUGWBecjWYa4hXC3CsH3+cFBZKjAepL74hqiEfsEyzKesft3NFd1AcVY9W5MRCK4
lUFiDbBtIgPkvPJeoEs/kFp3+OvJFDwi4K4Z6XzALyT0LXNx6w3kSfx0TLdNjXLD
O9a2dzwhHhPtCQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1P
cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUYJEUXnMb/ux0
WrzSh+bnhpi6GS0wHwYDVR0jBBgwFoAUpJjGgWED0xBnKntZmlNiAzjC0HswDQYJ
KoZIhvcNAQELBQADggGBAFbrwfsSciDFI97c7oqS8jtxOSa3c4B7xhmcgUkYCiaD
7mbZuqTUf4ltJJZXP/TJ44fhL0zVAvRXSXw1LE3YvLGOlBc6dM3D7DyL5pfUTUBY
ICt+NLfG5iHtkiZPPSfK2t5f4UGFwU/ERT62sLu4keLI5igi9J2jKSykN3u5SQ3s
Zsennow5zUsFkcz9hkB4RczlHRogA0SgVhELQbN1nYIqJJDRFZL+CmarDRTFMilk
7dXCacw6xt9vIc3ZXO+pu2g1ezgSPwOoUykQcL3UhAEIIyt+TRe3fafh5TXwd8tr
FAecAuz5Mqsmek5nEW9ZeYmxNz5VFwc4F61y4xFj7lI0frLCCAu3gVoqiQrW+WwR
e27z1Nm4uUcduFqj45Pu2eTyV3LZtLUbFvL5ZSPUCSk1wVmC2otX8ksFDDTO1rIy
l5Qd1g1P8bLuj8NG98J2zVOabtaxYCAIBPZ3dUh2eNrPKoLAvrgKh1MH+K2Eh5Oy
z1T4Eu+e5Kq/uQkZpI5QzA==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA1ledrM9R3x3bZypZAEi00DJYAmLS5F6Gg3+xpjE745UWKrjD
AY5KswavKKa3vZxoUz2omNSg4nYfLSowq7AI3VnZ8LwNo8lAeo7AX9elrsmzQzhr
2DCdCdbRhCWoiS/ba5tKIhlbgFnP+pB8jhC9qZuQJkpVaivywMW8rA9DRbeDcQjD
KhUi0ukVDYHDd9+FtNM3H1t3AUGWBecjWYa4hXC3CsH3+cFBZKjAepL74hqiEfsE
yzKesft3NFd1AcVY9W5MRCK4lUFiDbBtIgPkvPJeoEs/kFp3+OvJFDwi4K4Z6XzA
LyT0LXNx6w3kSfx0TLdNjXLDO9a2dzwhHhPtCQIDAQABAoIBAGMEGJfTMiwS+979
ph3GeJjRGO0JQAk1TYiDvcpbZiItJg9YSOV4GTP4u4PY+HqEPYFus2relu/mx2Iy
4kb9zCqNLmvSQ67M8pdrSJ093pEPJlvAPbmiQ3lfHmyghOnTDNb55tY3xphVZQmI
I7HxM9ydO4skva6NXNgGwLDvYBFc6z6d95ai/WEFWHOt5Mt7OVOWAHQ0lAOofWLA
2BwKmrQnCwMvm1TMoKaAU/ngTToUGBMIN1HwRcY6qDraZte5o3EDRABHB78OHrSu
I/Eoi//5C8A7iZ5Y189lMbahIN6xVMwHwwIqLptTV2GNZOKSiIXnM06vIf4CPZKl
3VlwBgECgYEA/BKnn23KtefA906QNkrIOXASLEE1T77NlTYIRDTsUoz6XTVSvOCI
ARxdsoLwFko5ICMhti9S/1G/MYH0BoJN8rbzvjmZDfwF612p0AYALyBlRgW+ID9L
41CJQcLWxeiQd/GcrUZmudVNUGXa8nsNHmFleGLchXeqU7M6fljJOkECgYEA2a56
yvYQgMF/SIPkxU1+WcQC6+JGc+ax220/lysBsDb4SkXomfGtFWbenxwamuQu+n67
DJWi9oJIi9Vj4eKOXS6vjCAkYeLgCpK6S26frPtxJuZwl/lF7mFl8Z4ZnJeiFJ4h
AXt5r9vqnOZtCnLqRRAlqF5OswWgv/mhJ6jpMMkCgYBMPaAxWlXLexMkOcDoiunQ
ZZM5i2eCfSVVEgiiCJfJyBYZhv1FX2wDWf8E9RGEzGJG1BloLxwdWS5I3RNfvJ2y
4Z8LVAR09Fsd+zBXWNlJZ7T53tbIjhx33m4FU9b9+P9pJ8zJo9eCMX+253e3i3xG
ShMUvGIShEUiF72DZXtHgQKBgDi867CfNmn5BW4nQqfSrQ5EsuY80lQ/WzhwX1TN
luERUuI5GomVnqGncHtUXfLlawFLqwF6t0E9cB9SfXhRDv5mvsbtUc5Zzj+zQu+K
ZAA4gaO8CLjz9jBOHr49kTtpootxM/Uo8+zMi3hd7yn8Def2b3pVKnorC10+eazW
sAFRAoGAet6fQbQD+4vZ1oukZcZhmVlIWTSZJ1vAGCcT/3E40pqpPY+Ho56Lcwh0
9f4TAykuGwFgqvZvR8yD2gpuISYGYplWqa1N6qxMaiVzmY5q1XW+O74xRH5Kz5fr
D+3j2x4EiyG7AYyZMOphDtBd/TSQQMYmGW6PiyM9ceIVnDK1Dd4=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,126 @@
/*-
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* Example of using EVP_MD_fetch and EVP_Digest* methods to calculate
* a digest of static buffers
* You can find SHA3 test vectors from NIST here:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
* For example, contains these lines:
Len = 80
Msg = 1ca984dcc913344370cf
MD = 6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd14816
* use xxd convert the hex message string to binary input for BIO_f_md:
* echo "1ca984dcc913344370cf" | xxd -r -p | ./BIO_f_md
* and then verify the output matches MD above.
*/
#include <string.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
/*-
* This demonstration will show how to digest data using
* a BIO configured with a message digest
* A message digest name may be passed as an argument.
* The default digest is SHA3-512
*/
int main(int argc, char *argv[])
{
int ret = EXIT_FAILURE;
OSSL_LIB_CTX *library_context = NULL;
BIO *input = NULL;
BIO *bio_digest = NULL, *reading = NULL;
EVP_MD *md = NULL;
unsigned char buffer[512];
int digest_size;
char *digest_value = NULL;
int j;
input = BIO_new_fd(fileno(stdin), 1);
if (input == NULL) {
fprintf(stderr, "BIO_new_fd() for stdin returned NULL\n");
goto cleanup;
}
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto cleanup;
}
/*
* Fetch a message digest by name
* The algorithm name is case insensitive.
* See providers(7) for details about algorithm fetching
*/
md = EVP_MD_fetch(library_context, "SHA3-512", NULL);
if (md == NULL) {
fprintf(stderr, "EVP_MD_fetch did not find SHA3-512.\n");
goto cleanup;
}
digest_size = EVP_MD_get_size(md);
if (digest_size <= 0) {
fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
goto cleanup;
}
digest_value = OPENSSL_malloc(digest_size);
if (digest_value == NULL) {
fprintf(stderr, "Can't allocate %lu bytes for the digest value.\n", (unsigned long)digest_size);
goto cleanup;
}
/* Make a bio that uses the digest */
bio_digest = BIO_new(BIO_f_md());
if (bio_digest == NULL) {
fprintf(stderr, "BIO_new(BIO_f_md()) returned NULL\n");
goto cleanup;
}
/* set our bio_digest BIO to digest data */
if (BIO_set_md(bio_digest, md) != 1) {
fprintf(stderr, "BIO_set_md failed.\n");
goto cleanup;
}
/*-
* We will use BIO chaining so that as we read, the digest gets updated
* See the man page for BIO_push
*/
reading = BIO_push(bio_digest, input);
while (BIO_read(reading, buffer, sizeof(buffer)) > 0)
;
/*-
* BIO_gets must be used to calculate the final
* digest value and then copy it to digest_value.
*/
if (BIO_gets(bio_digest, digest_value, digest_size) != digest_size) {
fprintf(stderr, "BIO_gets(bio_digest) failed\n");
goto cleanup;
}
for (j = 0; j < digest_size; j++) {
fprintf(stdout, "%02x", (unsigned char)digest_value[j]);
}
fprintf(stdout, "\n");
ret = EXIT_SUCCESS;
cleanup:
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
OPENSSL_free(digest_value);
BIO_free(input);
BIO_free(bio_digest);
EVP_MD_free(md);
OSSL_LIB_CTX_free(library_context);
return ret;
}

View File

@@ -0,0 +1,182 @@
/*-
* Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Example of using EVP_MD_fetch and EVP_Digest* methods to calculate
* a digest of static buffers
*/
#include <string.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
/*-
* This demonstration will show how to digest data using
* the soliloqy from Hamlet scene 1 act 3
* The soliloqy is split into two parts to demonstrate using EVP_DigestUpdate
* more than once.
*/
static const char *hamlet_1 =
"To be, or not to be, that is the question,\n"
"Whether tis nobler in the minde to suffer\n"
"The ſlings and arrowes of outragious fortune,\n"
"Or to take Armes again in a sea of troubles,\n"
"And by opposing, end them, to die to sleep;\n"
"No more, and by a sleep, to say we end\n"
"The heart-ache, and the thousand natural shocks\n"
"That flesh is heir to? tis a consumation\n"
"Devoutly to be wished. To die to sleep,\n"
"To sleepe, perchance to dreame, Aye, there's the rub,\n"
"For in that sleep of death what dreams may come\n"
"When we haue shuffled off this mortal coil\n"
"Must give us pause. There's the respect\n"
"That makes calamity of so long life:\n"
"For who would bear the Ships and Scorns of time,\n"
"The oppressor's wrong, the proud man's Contumely,\n"
"The pangs of dispised love, the Law's delay,\n"
;
static const char *hamlet_2 =
"The insolence of Office, and the spurns\n"
"That patient merit of the'unworthy takes,\n"
"When he himself might his Quietas make\n"
"With a bare bodkin? Who would fardels bear,\n"
"To grunt and sweat under a weary life,\n"
"But that the dread of something after death,\n"
"The undiscovered country, from whose bourn\n"
"No traveller returns, puzzles the will,\n"
"And makes us rather bear those ills we have,\n"
"Then fly to others we know not of?\n"
"Thus conscience does make cowards of us all,\n"
"And thus the native hue of Resolution\n"
"Is sickled o'er with the pale cast of Thought,\n"
"And enterprises of great pith and moment,\n"
"With this regard their currents turn awry,\n"
"And lose the name of Action. Soft you now,\n"
"The fair Ophelia? Nymph in thy Orisons\n"
"Be all my sins remember'd.\n"
;
/* The known value of the SHA3-512 digest of the above soliloqy */
static const unsigned char known_answer[] = {
0xbb, 0x69, 0xf8, 0x09, 0x9c, 0x2e, 0x00, 0x3d,
0xa4, 0x29, 0x5f, 0x59, 0x4b, 0x89, 0xe4, 0xd9,
0xdb, 0xa2, 0xe5, 0xaf, 0xa5, 0x87, 0x73, 0x9d,
0x83, 0x72, 0xcf, 0xea, 0x84, 0x66, 0xc1, 0xf9,
0xc9, 0x78, 0xef, 0xba, 0x3d, 0xe9, 0xc1, 0xff,
0xa3, 0x75, 0xc7, 0x58, 0x74, 0x8e, 0x9c, 0x1d,
0x14, 0xd9, 0xdd, 0xd1, 0xfd, 0x24, 0x30, 0xd6,
0x81, 0xca, 0x8f, 0x78, 0x29, 0x19, 0x9a, 0xfe,
};
static int demonstrate_digest(void)
{
OSSL_LIB_CTX *library_context;
int ret = 0;
const char *option_properties = NULL;
EVP_MD *message_digest = NULL;
EVP_MD_CTX *digest_context = NULL;
unsigned int digest_length;
unsigned char *digest_value = NULL;
unsigned int j;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto cleanup;
}
/*
* Fetch a message digest by name
* The algorithm name is case insensitive.
* See providers(7) for details about algorithm fetching
*/
message_digest = EVP_MD_fetch(library_context,
"SHA3-512", option_properties);
if (message_digest == NULL) {
fprintf(stderr, "EVP_MD_fetch could not find SHA3-512.");
goto cleanup;
}
/* Determine the length of the fetched digest type */
digest_length = EVP_MD_get_size(message_digest);
if (digest_length <= 0) {
fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
goto cleanup;
}
digest_value = OPENSSL_malloc(digest_length);
if (digest_value == NULL) {
fprintf(stderr, "No memory.\n");
goto cleanup;
}
/*
* Make a message digest context to hold temporary state
* during digest creation
*/
digest_context = EVP_MD_CTX_new();
if (digest_context == NULL) {
fprintf(stderr, "EVP_MD_CTX_new failed.\n");
goto cleanup;
}
/*
* Initialize the message digest context to use the fetched
* digest provider
*/
if (EVP_DigestInit(digest_context, message_digest) != 1) {
fprintf(stderr, "EVP_DigestInit failed.\n");
goto cleanup;
}
/* Digest parts one and two of the soliloqy */
if (EVP_DigestUpdate(digest_context, hamlet_1, strlen(hamlet_1)) != 1) {
fprintf(stderr, "EVP_DigestUpdate(hamlet_1) failed.\n");
goto cleanup;
}
if (EVP_DigestUpdate(digest_context, hamlet_2, strlen(hamlet_2)) != 1) {
fprintf(stderr, "EVP_DigestUpdate(hamlet_2) failed.\n");
goto cleanup;
}
if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) {
fprintf(stderr, "EVP_DigestFinal() failed.\n");
goto cleanup;
}
for (j=0; j<digest_length; j++) {
fprintf(stdout, "%02x", digest_value[j]);
}
fprintf(stdout, "\n");
/* Check digest_value against the known answer */
if ((size_t)digest_length != sizeof(known_answer)) {
fprintf(stdout, "Digest length(%d) not equal to known answer length(%lu).\n",
digest_length, sizeof(known_answer));
} else if (memcmp(digest_value, known_answer, digest_length) != 0) {
for (j=0; j<sizeof(known_answer); j++) {
fprintf(stdout, "%02x", known_answer[j] );
}
fprintf(stdout, "\nDigest does not match known answer\n");
} else {
fprintf(stdout, "Digest computed properly.\n");
ret = 1;
}
cleanup:
if (ret != 1)
ERR_print_errors_fp(stderr);
/* OpenSSL free functions will ignore NULL arguments */
EVP_MD_CTX_free(digest_context);
OPENSSL_free(digest_value);
EVP_MD_free(message_digest);
OSSL_LIB_CTX_free(library_context);
return ret;
}
int main(void)
{
return demonstrate_digest() ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -0,0 +1,136 @@
/*-
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*-
* Example of using EVP_MD_fetch and EVP_Digest* methods to calculate
* a digest of static buffers
* You can find SHA3 test vectors from NIST here:
* https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
* For example, contains these lines:
Len = 80
Msg = 1ca984dcc913344370cf
MD = 6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd14816
* use xxd convert the hex message string to binary input for EVP_MD_stdin:
* echo "1ca984dcc913344370cf" | xxd -r -p | ./EVP_MD_stdin
* and then verify the output matches MD above.
*/
#include <string.h>
#include <stdio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
/*-
* This demonstration will show how to digest data using
* a BIO created to read from stdin
*/
static int demonstrate_digest(BIO *input)
{
OSSL_LIB_CTX *library_context = NULL;
int ret = 0;
const char *option_properties = NULL;
EVP_MD *message_digest = NULL;
EVP_MD_CTX *digest_context = NULL;
unsigned int digest_length;
unsigned char *digest_value = NULL;
unsigned char buffer[512];
unsigned int ii;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto cleanup;
}
/*
* Fetch a message digest by name
* The algorithm name is case insensitive.
* See providers(7) for details about algorithm fetching
*/
message_digest = EVP_MD_fetch(library_context,
"SHA3-512", option_properties);
if (message_digest == NULL) {
fprintf(stderr, "EVP_MD_fetch could not find SHA3-512.");
ERR_print_errors_fp(stderr);
OSSL_LIB_CTX_free(library_context);
return 0;
}
/* Determine the length of the fetched digest type */
digest_length = EVP_MD_get_size(message_digest);
if (digest_length <= 0) {
fprintf(stderr, "EVP_MD_get_size returned invalid size.\n");
goto cleanup;
}
digest_value = OPENSSL_malloc(digest_length);
if (digest_value == NULL) {
fprintf(stderr, "No memory.\n");
goto cleanup;
}
/*
* Make a message digest context to hold temporary state
* during digest creation
*/
digest_context = EVP_MD_CTX_new();
if (digest_context == NULL) {
fprintf(stderr, "EVP_MD_CTX_new failed.\n");
ERR_print_errors_fp(stderr);
goto cleanup;
}
/*
* Initialize the message digest context to use the fetched
* digest provider
*/
if (EVP_DigestInit(digest_context, message_digest) != 1) {
fprintf(stderr, "EVP_DigestInit failed.\n");
ERR_print_errors_fp(stderr);
goto cleanup;
}
while ((ii = BIO_read(input, buffer, sizeof(buffer))) > 0) {
if (EVP_DigestUpdate(digest_context, buffer, ii) != 1) {
fprintf(stderr, "EVP_DigestUpdate() failed.\n");
goto cleanup;
}
}
if (EVP_DigestFinal(digest_context, digest_value, &digest_length) != 1) {
fprintf(stderr, "EVP_DigestFinal() failed.\n");
goto cleanup;
}
ret = 1;
for (ii=0; ii<digest_length; ii++) {
fprintf(stdout, "%02x", digest_value[ii]);
}
fprintf(stdout, "\n");
cleanup:
if (ret != 1)
ERR_print_errors_fp(stderr);
/* OpenSSL free functions will ignore NULL arguments */
EVP_MD_CTX_free(digest_context);
OPENSSL_free(digest_value);
EVP_MD_free(message_digest);
OSSL_LIB_CTX_free(library_context);
return ret;
}
int main(void)
{
int ret = EXIT_FAILURE;
BIO *input = BIO_new_fd(fileno(stdin), 1);
if (input != NULL) {
ret = (demonstrate_digest(input) ? EXIT_SUCCESS : EXIT_FAILURE);
BIO_free(input);
}
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
return ret;
}

View File

@@ -0,0 +1,132 @@
/*-
* Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/core_names.h>
/*
* Example of using an extendable-output hash function (XOF). A XOF is a hash
* function with configurable output length and which can generate an
* arbitrarily large output.
*
* This example uses SHAKE256, an extendable output variant of SHA3 (Keccak).
*
* To generate different output lengths, you can pass a single integer argument
* on the command line, which is the output size in bytes. By default, a 20-byte
* output is generated and (for this length only) a known answer test is
* performed.
*/
/* Our input to the XOF hash function. */
static const char message[] = "This is a test message.";
/* Expected output when an output length of 20 bytes is used. */
static const unsigned char known_answer[] = {
0x52, 0x97, 0x93, 0x78, 0x27, 0x58, 0x7d, 0x62,
0x8b, 0x00, 0x25, 0xb5, 0xec, 0x39, 0x5e, 0x2d,
0x7f, 0x3e, 0xd4, 0x19
};
/*
* A property query used for selecting the SHAKE256 implementation.
*/
static const char *propq = NULL;
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
OSSL_LIB_CTX *libctx = NULL;
EVP_MD *md = NULL;
EVP_MD_CTX *ctx = NULL;
unsigned int digest_len = 20;
int digest_len_i;
unsigned char *digest = NULL;
/* Allow digest length to be changed for demonstration purposes. */
if (argc > 1) {
digest_len_i = atoi(argv[1]);
if (digest_len_i <= 0) {
fprintf(stderr, "Specify a non-negative digest length\n");
goto end;
}
digest_len = (unsigned int)digest_len_i;
}
/*
* Retrieve desired algorithm. This must be a hash algorithm which supports
* XOF.
*/
md = EVP_MD_fetch(libctx, "SHAKE256", propq);
if (md == NULL) {
fprintf(stderr, "Failed to retrieve SHAKE256 algorithm\n");
goto end;
}
/* Create context. */
ctx = EVP_MD_CTX_new();
if (ctx == NULL) {
fprintf(stderr, "Failed to create digest context\n");
goto end;
}
/* Initialize digest context. */
if (EVP_DigestInit(ctx, md) == 0) {
fprintf(stderr, "Failed to initialize digest\n");
goto end;
}
/*
* Feed our message into the digest function.
* This may be called multiple times.
*/
if (EVP_DigestUpdate(ctx, message, sizeof(message)) == 0) {
fprintf(stderr, "Failed to hash input message\n");
goto end;
}
/* Allocate enough memory for our digest length. */
digest = OPENSSL_malloc(digest_len);
if (digest == NULL) {
fprintf(stderr, "Failed to allocate memory for digest\n");
goto end;
}
/* Get computed digest. The digest will be of whatever length we specify. */
if (EVP_DigestFinalXOF(ctx, digest, digest_len) == 0) {
fprintf(stderr, "Failed to finalize hash\n");
goto end;
}
printf("Output digest:\n");
BIO_dump_indent_fp(stdout, digest, digest_len, 2);
/* If digest length is 20 bytes, check it matches our known answer. */
if (digest_len == 20) {
/*
* Always use a constant-time function such as CRYPTO_memcmp
* when comparing cryptographic values. Do not use memcmp(3).
*/
if (CRYPTO_memcmp(digest, known_answer, sizeof(known_answer)) != 0) {
fprintf(stderr, "Output does not match expected result\n");
goto end;
}
}
ret = EXIT_SUCCESS;
end:
OPENSSL_free(digest);
EVP_MD_CTX_free(ctx);
EVP_MD_free(md);
OSSL_LIB_CTX_free(libctx);
return ret;
}

View File

@@ -0,0 +1,37 @@
#
# To run the demos when linked with a shared library (default) ensure
# that libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./EVP_MD_demo
TESTS = EVP_MD_demo \
EVP_MD_stdin \
EVP_MD_xof \
BIO_f_md
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
EVP_MD_demo: EVP_MD_demo.o
EVP_MD_stdin: EVP_MD_stdin.o
EVP_MD_xof: EVP_MD_xof.o
BIO_f_md: BIO_f_md.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) *.o $(TESTS)
.PHONY: test
# Since some of these tests use stdin, we use the source file as stdin
# when running the tests
test: all
@echo "\nDigest tests:"
@set -e; for tst in $(TESTS); do \
echo "\n"$$tst; \
cat $$tst.c | ./$$tst; \
done

View File

@@ -0,0 +1,20 @@
PROGRAMS{noinst} = EVP_MD_demo \
EVP_MD_stdin \
EVP_MD_xof \
BIO_f_md
INCLUDE[EVP_MD_demo]=../../include
SOURCE[EVP_MD_demo]=EVP_MD_demo.c
DEPEND[EVP_MD_demo]=../../libcrypto
INCLUDE[EVP_MD_stdin]=../../include
SOURCE[EVP_MD_stdin]=EVP_MD_stdin.c
DEPEND[EVP_MD_stdin]=../../libcrypto
INCLUDE[EVP_MD_xof]=../../include
SOURCE[EVP_MD_xof]=EVP_MD_xof.c
DEPEND[EVP_MD_xof]=../../libcrypto
INCLUDE[BIO_f_md]=../../include
SOURCE[BIO_f_md]=BIO_f_md.c
DEPEND[BIO_f_md]=../../libcrypto

View File

@@ -0,0 +1,28 @@
#
# To run the demos when linked with a shared library (default) ensure
# that libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./rsa_encode
TESTS = ec_encode \
rsa_encode
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
ec_encode: ec_encode.o
rsa_encode: rsa_encode.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) *.o $(TESTS)
.PHONY: test
test: all
@echo "\nencode tests:"
@echo "skipped"

View File

@@ -0,0 +1,17 @@
#
# To run the demos when linked with a shared library (default) ensure
# that libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./rsa_encode
PROGRAMS{noinst} = ec_encode \
rsa_encode
INCLUDE[ec_encode]=../../include
SOURCE[ec_encode]=ec_encode.c
DEPEND[ec_encode]=../../libcrypto
INCLUDE[rsa_encode]=../../include
SOURCE[rsa_encode]=rsa_encode.c
DEPEND[rsa_encode]=../../libcrypto

View File

@@ -0,0 +1,205 @@
/*-
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/decoder.h>
#include <openssl/encoder.h>
#include <openssl/evp.h>
/*
* Example showing the encoding and decoding of EC public and private keys. A
* PEM-encoded EC key is read in from stdin, decoded, and then re-encoded and
* output for demonstration purposes. Both public and private keys are accepted.
*
* This can be used to load EC keys from a file or save EC keys to a file.
*/
/* A property query used for selecting algorithm implementations. */
static const char *propq = NULL;
/*
* Load a PEM-encoded EC key from a file, optionally decrypting it with a
* supplied passphrase.
*/
static EVP_PKEY *load_key(OSSL_LIB_CTX *libctx, FILE *f, const char *passphrase)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
OSSL_DECODER_CTX *dctx = NULL;
int selection = 0;
/*
* Create PEM decoder context expecting an EC key.
*
* For raw (non-PEM-encoded) keys, change "PEM" to "DER".
*
* The selection argument here specifies whether we are willing to accept a
* public key, private key, or either. If it is set to zero, either will be
* accepted. If set to EVP_PKEY_KEYPAIR, a private key will be required, and
* if set to EVP_PKEY_PUBLIC_KEY, a public key will be required.
*/
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "EC",
selection,
libctx, propq);
if (dctx == NULL) {
fprintf(stderr, "OSSL_DECODER_CTX_new_for_pkey() failed\n");
goto cleanup;
}
/*
* Set passphrase if provided; needed to decrypt encrypted PEM files.
* If the input is not encrypted, any passphrase provided is ignored.
*
* Alternative methods for specifying passphrases exist, such as a callback
* (see OSSL_DECODER_CTX_set_passphrase_cb(3)), which may be more useful for
* interactive applications which do not know if a passphrase should be
* prompted for in advance, or for GUI applications.
*/
if (passphrase != NULL) {
if (OSSL_DECODER_CTX_set_passphrase(dctx,
(const unsigned char *)passphrase,
strlen(passphrase)) == 0) {
fprintf(stderr, "OSSL_DECODER_CTX_set_passphrase() failed\n");
goto cleanup;
}
}
/* Do the decode, reading from file. */
if (OSSL_DECODER_from_fp(dctx, f) == 0) {
fprintf(stderr, "OSSL_DECODER_from_fp() failed\n");
goto cleanup;
}
ret = 1;
cleanup:
OSSL_DECODER_CTX_free(dctx);
/*
* pkey is created by OSSL_DECODER_CTX_new_for_pkey, but we
* might fail subsequently, so ensure it's properly freed
* in this case.
*/
if (ret == 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
return pkey;
}
/*
* Store a EC public or private key to a file using PEM encoding.
*
* If a passphrase is supplied, the file is encrypted, otherwise
* it is unencrypted.
*/
static int store_key(EVP_PKEY *pkey, FILE *f, const char *passphrase)
{
int ret = 0;
int selection;
OSSL_ENCODER_CTX *ectx = NULL;
/*
* Create a PEM encoder context.
*
* For raw (non-PEM-encoded) output, change "PEM" to "DER".
*
* The selection argument controls whether the private key is exported
* (EVP_PKEY_KEYPAIR), or only the public key (EVP_PKEY_PUBLIC_KEY). The
* former will fail if we only have a public key.
*
* Note that unlike the decode API, you cannot specify zero here.
*
* Purely for the sake of demonstration, here we choose to export the whole
* key if a passphrase is provided and the public key otherwise.
*/
selection = (passphrase != NULL)
? EVP_PKEY_KEYPAIR
: EVP_PKEY_PUBLIC_KEY;
ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "PEM", NULL, propq);
if (ectx == NULL) {
fprintf(stderr, "OSSL_ENCODER_CTX_new_for_pkey() failed\n");
goto cleanup;
}
/*
* Set passphrase if provided; the encoded output will then be encrypted
* using the passphrase.
*
* Alternative methods for specifying passphrases exist, such as a callback
* (see OSSL_ENCODER_CTX_set_passphrase_cb(3), just as for OSSL_DECODER_CTX;
* however you are less likely to need them as you presumably know whether
* encryption is desired in advance.
*
* Note that specifying a passphrase alone is not enough to cause the
* key to be encrypted. You must set both a cipher and a passphrase.
*/
if (passphrase != NULL) {
/*
* Set cipher. Let's use AES-256-CBC, because it is
* more quantum resistant.
*/
if (OSSL_ENCODER_CTX_set_cipher(ectx, "AES-256-CBC", propq) == 0) {
fprintf(stderr, "OSSL_ENCODER_CTX_set_cipher() failed\n");
goto cleanup;
}
/* Set passphrase. */
if (OSSL_ENCODER_CTX_set_passphrase(ectx,
(const unsigned char *)passphrase,
strlen(passphrase)) == 0) {
fprintf(stderr, "OSSL_ENCODER_CTX_set_passphrase() failed\n");
goto cleanup;
}
}
/* Do the encode, writing to the given file. */
if (OSSL_ENCODER_to_fp(ectx, f) == 0) {
fprintf(stderr, "OSSL_ENCODER_to_fp() failed\n");
goto cleanup;
}
ret = 1;
cleanup:
OSSL_ENCODER_CTX_free(ectx);
return ret;
}
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
OSSL_LIB_CTX *libctx = NULL;
EVP_PKEY *pkey = NULL;
const char *passphrase_in = NULL, *passphrase_out = NULL;
/* usage: ec_encode <passphrase-in> <passphrase-out> */
if (argc > 1 && argv[1][0])
passphrase_in = argv[1];
if (argc > 2 && argv[2][0])
passphrase_out = argv[2];
/* Decode PEM key from stdin and then PEM encode it to stdout. */
pkey = load_key(libctx, stdin, passphrase_in);
if (pkey == NULL) {
fprintf(stderr, "Failed to decode key\n");
goto cleanup;
}
if (store_key(pkey, stdout, passphrase_out) == 0) {
fprintf(stderr, "Failed to encode key\n");
goto cleanup;
}
ret = EXIT_SUCCESS;
cleanup:
EVP_PKEY_free(pkey);
OSSL_LIB_CTX_free(libctx);
return ret;
}

View File

@@ -0,0 +1,202 @@
/*-
* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/decoder.h>
#include <openssl/encoder.h>
#include <openssl/evp.h>
/*
* Example showing the encoding and decoding of RSA public and private keys. A
* PEM-encoded RSA key is read in from stdin, decoded, and then re-encoded and
* output for demonstration purposes. Both public and private keys are accepted.
*
* This can be used to load RSA keys from a file or save RSA keys to a file.
*/
/* A property query used for selecting algorithm implementations. */
static const char *propq = NULL;
/*
* Load a PEM-encoded RSA key from a file, optionally decrypting it with a
* supplied passphrase.
*/
static EVP_PKEY *load_key(OSSL_LIB_CTX *libctx, FILE *f, const char *passphrase)
{
int ret = 0;
EVP_PKEY *pkey = NULL;
OSSL_DECODER_CTX *dctx = NULL;
int selection = 0;
/*
* Create PEM decoder context expecting an RSA key.
*
* For raw (non-PEM-encoded) keys, change "PEM" to "DER".
*
* The selection argument here specifies whether we are willing to accept a
* public key, private key, or either. If it is set to zero, either will be
* accepted. If set to EVP_PKEY_KEYPAIR, a private key will be required, and
* if set to EVP_PKEY_PUBLIC_KEY, a public key will be required.
*/
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "RSA",
selection,
libctx, propq);
if (dctx == NULL) {
fprintf(stderr, "OSSL_DECODER_CTX_new_for_pkey() failed\n");
goto cleanup;
}
/*
* Set passphrase if provided; needed to decrypt encrypted PEM files.
* If the input is not encrypted, any passphrase provided is ignored.
*
* Alternative methods for specifying passphrases exist, such as a callback
* (see OSSL_DECODER_CTX_set_passphrase_cb(3)), which may be more useful for
* interactive applications which do not know if a passphrase should be
* prompted for in advance, or for GUI applications.
*/
if (passphrase != NULL) {
if (OSSL_DECODER_CTX_set_passphrase(dctx,
(const unsigned char *)passphrase,
strlen(passphrase)) == 0) {
fprintf(stderr, "OSSL_DECODER_CTX_set_passphrase() failed\n");
goto cleanup;
}
}
/* Do the decode, reading from file. */
if (OSSL_DECODER_from_fp(dctx, f) == 0) {
fprintf(stderr, "OSSL_DECODER_from_fp() failed\n");
goto cleanup;
}
ret = 1;
cleanup:
OSSL_DECODER_CTX_free(dctx);
/*
* pkey is created by OSSL_DECODER_CTX_new_for_pkey, but we
* might fail subsequently, so ensure it's properly freed
* in this case.
*/
if (ret == 0) {
EVP_PKEY_free(pkey);
pkey = NULL;
}
return pkey;
}
/*
* Store an RSA public or private key to a file using PEM encoding.
*
* If a passphrase is supplied, the file is encrypted, otherwise
* it is unencrypted.
*/
static int store_key(EVP_PKEY *pkey, FILE *f, const char *passphrase)
{
int ret = 0;
int selection;
OSSL_ENCODER_CTX *ectx = NULL;
/*
* Create a PEM encoder context.
*
* For raw (non-PEM-encoded) output, change "PEM" to "DER".
*
* The selection argument controls whether the private key is exported
* (EVP_PKEY_KEYPAIR), or only the public key (EVP_PKEY_PUBLIC_KEY). The
* former will fail if we only have a public key.
*
* Note that unlike the decode API, you cannot specify zero here.
*
* Purely for the sake of demonstration, here we choose to export the whole
* key if a passphrase is provided and the public key otherwise.
*/
selection = (passphrase != NULL)
? EVP_PKEY_KEYPAIR
: EVP_PKEY_PUBLIC_KEY;
ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "PEM", NULL, propq);
if (ectx == NULL) {
fprintf(stderr, "OSSL_ENCODER_CTX_new_for_pkey() failed\n");
goto cleanup;
}
/*
* Set passphrase if provided; the encoded output will then be encrypted
* using the passphrase.
*
* Alternative methods for specifying passphrases exist, such as a callback
* (see OSSL_ENCODER_CTX_set_passphrase_cb(3), just as for OSSL_DECODER_CTX;
* however you are less likely to need them as you presumably know whether
* encryption is desired in advance.
*
* Note that specifying a passphrase alone is not enough to cause the
* key to be encrypted. You must set both a cipher and a passphrase.
*/
if (passphrase != NULL) {
/* Set cipher. AES-128-CBC is a reasonable default. */
if (OSSL_ENCODER_CTX_set_cipher(ectx, "AES-128-CBC", propq) == 0) {
fprintf(stderr, "OSSL_ENCODER_CTX_set_cipher() failed\n");
goto cleanup;
}
/* Set passphrase. */
if (OSSL_ENCODER_CTX_set_passphrase(ectx,
(const unsigned char *)passphrase,
strlen(passphrase)) == 0) {
fprintf(stderr, "OSSL_ENCODER_CTX_set_passphrase() failed\n");
goto cleanup;
}
}
/* Do the encode, writing to the given file. */
if (OSSL_ENCODER_to_fp(ectx, f) == 0) {
fprintf(stderr, "OSSL_ENCODER_to_fp() failed\n");
goto cleanup;
}
ret = 1;
cleanup:
OSSL_ENCODER_CTX_free(ectx);
return ret;
}
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
OSSL_LIB_CTX *libctx = NULL;
EVP_PKEY *pkey = NULL;
const char *passphrase_in = NULL, *passphrase_out = NULL;
/* usage: rsa_encode <passphrase-in> <passphrase-out> */
if (argc > 1 && argv[1][0])
passphrase_in = argv[1];
if (argc > 2 && argv[2][0])
passphrase_out = argv[2];
/* Decode PEM key from stdin and then PEM encode it to stdout. */
pkey = load_key(libctx, stdin, passphrase_in);
if (pkey == NULL) {
fprintf(stderr, "Failed to decode key\n");
goto cleanup;
}
if (store_key(pkey, stdout, passphrase_out) == 0) {
fprintf(stderr, "Failed to encode key\n");
goto cleanup;
}
ret = EXIT_SUCCESS;
cleanup:
EVP_PKEY_free(pkey);
OSSL_LIB_CTX_free(libctx);
return ret;
}

View File

@@ -0,0 +1,29 @@
#
# To run the demos when linked with a shared library (default) ensure
# that libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./rsa_encrypt
TESTS = rsa_encrypt
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
rsa_encrypt: rsa_encrypt.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) *.o $(TESTS)
.PHONY: test
test: all
@echo "\nEncrypt tests:"
@set -e; for tst in $(TESTS); do \
echo "\n"$$tst; \
LD_LIBRARY_PATH=../.. ./$$tst; \
done

View File

@@ -0,0 +1,11 @@
#
# To run the demos when linked with a shared library (default) ensure
# that libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./rsa_encrypt
PROGRAMS{noinst} = rsa_encrypt
INCLUDE[rsa_encrypt]=../../include
SOURCE[rsa_encrypt]=rsa_encrypt.c
DEPEND[rsa_encrypt]=../../libcrypto

View File

@@ -0,0 +1,243 @@
/*-
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* An example that uses EVP_PKEY_encrypt and EVP_PKEY_decrypt methods
* to encrypt and decrypt data using an RSA keypair.
* RSA encryption produces different encrypted output each time it is run,
* hence this is not a known answer test.
*/
#include <stdio.h>
#include <stdlib.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/decoder.h>
#include <openssl/core_names.h>
#include "rsa_encrypt.h"
/* Input data to encrypt */
static const unsigned char msg[] =
"To be, or not to be, that is the question,\n"
"Whether tis nobler in the minde to suffer\n"
"The slings and arrowes of outragious fortune,\n"
"Or to take Armes again in a sea of troubles";
/*
* For do_encrypt(), load an RSA public key from pub_key_der[].
* For do_decrypt(), load an RSA private key from priv_key_der[].
*/
static EVP_PKEY *get_key(OSSL_LIB_CTX *libctx, const char *propq, int public)
{
OSSL_DECODER_CTX *dctx = NULL;
EVP_PKEY *pkey = NULL;
int selection;
const unsigned char *data;
size_t data_len;
if (public) {
selection = EVP_PKEY_PUBLIC_KEY;
data = pub_key_der;
data_len = sizeof(pub_key_der);
} else {
selection = EVP_PKEY_KEYPAIR;
data = priv_key_der;
data_len = sizeof(priv_key_der);
}
dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, "RSA",
selection, libctx, propq);
(void)OSSL_DECODER_from_data(dctx, &data, &data_len);
OSSL_DECODER_CTX_free(dctx);
return pkey;
}
/* Set optional parameters for RSA OAEP Padding */
static void set_optional_params(OSSL_PARAM *p, const char *propq)
{
static unsigned char label[] = "label";
/* "pkcs1" is used by default if the padding mode is not set */
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_PAD_MODE,
OSSL_PKEY_RSA_PAD_MODE_OAEP, 0);
/* No oaep_label is used if this is not set */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
label, sizeof(label));
/* "SHA1" is used if this is not set */
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST,
"SHA256", 0);
/*
* If a non default property query needs to be specified when fetching the
* OAEP digest then it needs to be specified here.
*/
if (propq != NULL)
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS,
(char *)propq, 0);
/*
* OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST and
* OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS can also be optionally added
* here if the MGF1 digest differs from the OAEP digest.
*/
*p = OSSL_PARAM_construct_end();
}
/*
* The length of the input data that can be encrypted is limited by the
* RSA key length minus some additional bytes that depends on the padding mode.
*
*/
static int do_encrypt(OSSL_LIB_CTX *libctx,
const unsigned char *in, size_t in_len,
unsigned char **out, size_t *out_len)
{
int ret = 0, public = 1;
size_t buf_len = 0;
unsigned char *buf = NULL;
const char *propq = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pub_key = NULL;
OSSL_PARAM params[5];
/* Get public key */
pub_key = get_key(libctx, propq, public);
if (pub_key == NULL) {
fprintf(stderr, "Get public key failed.\n");
goto cleanup;
}
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pub_key, propq);
if (ctx == NULL) {
fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey() failed.\n");
goto cleanup;
}
set_optional_params(params, propq);
/* If no optional parameters are required then NULL can be passed */
if (EVP_PKEY_encrypt_init_ex(ctx, params) <= 0) {
fprintf(stderr, "EVP_PKEY_encrypt_init_ex() failed.\n");
goto cleanup;
}
/* Calculate the size required to hold the encrypted data */
if (EVP_PKEY_encrypt(ctx, NULL, &buf_len, in, in_len) <= 0) {
fprintf(stderr, "EVP_PKEY_encrypt() failed.\n");
goto cleanup;
}
buf = OPENSSL_zalloc(buf_len);
if (buf == NULL) {
fprintf(stderr, "Malloc failed.\n");
goto cleanup;
}
if (EVP_PKEY_encrypt(ctx, buf, &buf_len, in, in_len) <= 0) {
fprintf(stderr, "EVP_PKEY_encrypt() failed.\n");
goto cleanup;
}
*out_len = buf_len;
*out = buf;
fprintf(stdout, "Encrypted:\n");
BIO_dump_indent_fp(stdout, buf, buf_len, 2);
fprintf(stdout, "\n");
ret = 1;
cleanup:
if (!ret)
OPENSSL_free(buf);
EVP_PKEY_free(pub_key);
EVP_PKEY_CTX_free(ctx);
return ret;
}
static int do_decrypt(OSSL_LIB_CTX *libctx, const unsigned char *in, size_t in_len,
unsigned char **out, size_t *out_len)
{
int ret = 0, public = 0;
size_t buf_len = 0;
unsigned char *buf = NULL;
const char *propq = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *priv_key = NULL;
OSSL_PARAM params[5];
/* Get private key */
priv_key = get_key(libctx, propq, public);
if (priv_key == NULL) {
fprintf(stderr, "Get private key failed.\n");
goto cleanup;
}
ctx = EVP_PKEY_CTX_new_from_pkey(libctx, priv_key, propq);
if (ctx == NULL) {
fprintf(stderr, "EVP_PKEY_CTX_new_from_pkey() failed.\n");
goto cleanup;
}
/* The parameters used for encryption must also be used for decryption */
set_optional_params(params, propq);
/* If no optional parameters are required then NULL can be passed */
if (EVP_PKEY_decrypt_init_ex(ctx, params) <= 0) {
fprintf(stderr, "EVP_PKEY_decrypt_init_ex() failed.\n");
goto cleanup;
}
/* Calculate the size required to hold the decrypted data */
if (EVP_PKEY_decrypt(ctx, NULL, &buf_len, in, in_len) <= 0) {
fprintf(stderr, "EVP_PKEY_decrypt() failed.\n");
goto cleanup;
}
buf = OPENSSL_zalloc(buf_len);
if (buf == NULL) {
fprintf(stderr, "Malloc failed.\n");
goto cleanup;
}
if (EVP_PKEY_decrypt(ctx, buf, &buf_len, in, in_len) <= 0) {
fprintf(stderr, "EVP_PKEY_decrypt() failed.\n");
goto cleanup;
}
*out_len = buf_len;
*out = buf;
fprintf(stdout, "Decrypted:\n");
BIO_dump_indent_fp(stdout, buf, buf_len, 2);
fprintf(stdout, "\n");
ret = 1;
cleanup:
if (!ret)
OPENSSL_free(buf);
EVP_PKEY_free(priv_key);
EVP_PKEY_CTX_free(ctx);
return ret;
}
int main(void)
{
int ret = EXIT_FAILURE;
size_t msg_len = sizeof(msg) - 1;
size_t encrypted_len = 0, decrypted_len = 0;
unsigned char *encrypted = NULL, *decrypted = NULL;
OSSL_LIB_CTX *libctx = NULL;
if (!do_encrypt(libctx, msg, msg_len, &encrypted, &encrypted_len)) {
fprintf(stderr, "encryption failed.\n");
goto cleanup;
}
if (!do_decrypt(libctx, encrypted, encrypted_len,
&decrypted, &decrypted_len)) {
fprintf(stderr, "decryption failed.\n");
goto cleanup;
}
if (CRYPTO_memcmp(msg, decrypted, decrypted_len) != 0) {
fprintf(stderr, "Decrypted data does not match expected value\n");
goto cleanup;
}
ret = EXIT_SUCCESS;
cleanup:
OPENSSL_free(decrypted);
OPENSSL_free(encrypted);
OSSL_LIB_CTX_free(libctx);
if (ret != EXIT_SUCCESS)
ERR_print_errors_fp(stderr);
return ret;
}

View File

@@ -0,0 +1,141 @@
/*-
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Private RSA key used for decryption */
static const unsigned char priv_key_der[] = {
0x30, 0x82, 0x04, 0xa4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
0xc2, 0x44, 0xbc, 0xcf, 0x5b, 0xca, 0xcd, 0x80, 0x77, 0xae, 0xf9, 0x7a,
0x34, 0xbb, 0x37, 0x6f, 0x5c, 0x76, 0x4c, 0xe4, 0xbb, 0x0c, 0x1d, 0xe7,
0xfe, 0x0f, 0xda, 0xcf, 0x8c, 0x56, 0x65, 0x72, 0x6e, 0x2c, 0xf9, 0xfd,
0x87, 0x43, 0xeb, 0x4c, 0x26, 0xb1, 0xd3, 0xf0, 0x87, 0xb1, 0x18, 0x68,
0x14, 0x7d, 0x3c, 0x2a, 0xfa, 0xc2, 0x5d, 0x70, 0x19, 0x11, 0x00, 0x2e,
0xb3, 0x9c, 0x8e, 0x38, 0x08, 0xbe, 0xe3, 0xeb, 0x7d, 0x6e, 0xc7, 0x19,
0xc6, 0x7f, 0x59, 0x48, 0x84, 0x1b, 0xe3, 0x27, 0x30, 0x46, 0x30, 0xd3,
0xfc, 0xfc, 0xb3, 0x35, 0x75, 0xc4, 0x31, 0x1a, 0xc0, 0xc2, 0x4c, 0x0b,
0xc7, 0x01, 0x95, 0xb2, 0xdc, 0x17, 0x77, 0x9b, 0x09, 0x15, 0x04, 0xbc,
0xdb, 0x57, 0x0b, 0x26, 0xda, 0x59, 0x54, 0x0d, 0x6e, 0xb7, 0x89, 0xbc,
0x53, 0x9d, 0x5f, 0x8c, 0xad, 0x86, 0x97, 0xd2, 0x48, 0x4f, 0x5c, 0x94,
0xdd, 0x30, 0x2f, 0xcf, 0xfc, 0xde, 0x20, 0x31, 0x25, 0x9d, 0x29, 0x25,
0x78, 0xb7, 0xd2, 0x5b, 0x5d, 0x99, 0x5b, 0x08, 0x12, 0x81, 0x79, 0x89,
0xa0, 0xcf, 0x8f, 0x40, 0xb1, 0x77, 0x72, 0x3b, 0x13, 0xfc, 0x55, 0x43,
0x70, 0x29, 0xd5, 0x41, 0xed, 0x31, 0x4b, 0x2d, 0x6c, 0x7d, 0xcf, 0x99,
0x5f, 0xd1, 0x72, 0x9f, 0x8b, 0x32, 0x96, 0xde, 0x5d, 0x8b, 0x19, 0x77,
0x75, 0xff, 0x09, 0xbf, 0x26, 0xe9, 0xd7, 0x3d, 0xc7, 0x1a, 0x81, 0xcf,
0x05, 0x1b, 0x89, 0xbf, 0x45, 0x32, 0xbf, 0x5e, 0xc9, 0xe3, 0x5c, 0x33,
0x4a, 0x72, 0x47, 0xf4, 0x24, 0xae, 0x9b, 0x38, 0x24, 0x76, 0x9a, 0xa2,
0x9a, 0x50, 0x50, 0x49, 0xf5, 0x26, 0xb9, 0x55, 0xa6, 0x47, 0xc9, 0x14,
0xa2, 0xca, 0xd4, 0xa8, 0x8a, 0x9f, 0xe9, 0x5a, 0x5a, 0x12, 0xaa, 0x30,
0xd5, 0x78, 0x8b, 0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01,
0x00, 0x22, 0x5d, 0xb9, 0x8e, 0xef, 0x1c, 0x91, 0xbd, 0x03, 0xaf, 0x1a,
0xe8, 0x00, 0xf3, 0x0b, 0x8b, 0xf2, 0x2d, 0xe5, 0x4d, 0x63, 0x3f, 0x71,
0xfc, 0xeb, 0xc7, 0x4f, 0x3c, 0x7f, 0x05, 0x7b, 0x9d, 0xc2, 0x1a, 0xc7,
0xc0, 0x8f, 0x50, 0xb7, 0x0b, 0xba, 0x1e, 0xa4, 0x30, 0xfd, 0x38, 0x19,
0x6a, 0xb4, 0x11, 0x31, 0x77, 0x22, 0xf4, 0x06, 0x46, 0x81, 0xd0, 0xad,
0x99, 0x15, 0x62, 0x01, 0x10, 0xad, 0x8f, 0x63, 0x4f, 0x71, 0xd9, 0x8a,
0x74, 0x27, 0x56, 0xb8, 0xeb, 0x28, 0x9f, 0xac, 0x4f, 0xee, 0xec, 0xc3,
0xcf, 0x84, 0x86, 0x09, 0x87, 0xd0, 0x04, 0xfc, 0x70, 0xd0, 0x9f, 0xae,
0x87, 0x38, 0xd5, 0xb1, 0x6f, 0x3a, 0x1b, 0x16, 0xa8, 0x00, 0xf3, 0xcc,
0x6a, 0x42, 0x5d, 0x04, 0x16, 0x83, 0xf2, 0xe0, 0x79, 0x1d, 0xd8, 0x6f,
0x0f, 0xb7, 0x34, 0xf4, 0x45, 0xb5, 0x1e, 0xc5, 0xb5, 0x78, 0xa7, 0xd3,
0xa3, 0x23, 0x35, 0xbc, 0x7b, 0x01, 0x59, 0x7d, 0xee, 0xb9, 0x4f, 0xda,
0x28, 0xad, 0x5d, 0x25, 0xab, 0x66, 0x6a, 0xb0, 0x61, 0xf6, 0x12, 0xa7,
0xee, 0xd1, 0xe7, 0xb1, 0x8b, 0x91, 0x29, 0xba, 0xb5, 0xf8, 0x78, 0xc8,
0x6b, 0x76, 0x67, 0x32, 0xe8, 0xf3, 0x4e, 0x59, 0xba, 0xc1, 0x44, 0xc0,
0xec, 0x8d, 0x7c, 0x63, 0xb2, 0x6e, 0x0c, 0xb9, 0x33, 0x42, 0x0c, 0x8d,
0xae, 0x4e, 0x54, 0xc8, 0x8a, 0xef, 0xf9, 0x47, 0xc8, 0x99, 0x84, 0xc8,
0x46, 0xf6, 0xa6, 0x53, 0x59, 0xf8, 0x60, 0xe3, 0xd7, 0x1d, 0x10, 0x95,
0xf5, 0x6d, 0xf4, 0xa3, 0x18, 0x40, 0xd7, 0x14, 0x04, 0xac, 0x8c, 0x69,
0xd6, 0x14, 0xdc, 0xd8, 0xcc, 0xbc, 0x1c, 0xac, 0xd7, 0x21, 0x2b, 0x7e,
0x29, 0x88, 0x06, 0xa0, 0xf4, 0x06, 0x08, 0x14, 0x04, 0x4d, 0x32, 0x33,
0x84, 0x9c, 0x20, 0x8e, 0xcf, 0x02, 0x81, 0x81, 0x00, 0xf3, 0xf9, 0xbd,
0xd5, 0x43, 0x6f, 0x27, 0x4a, 0x92, 0xd6, 0x18, 0x3d, 0x4b, 0xf1, 0x77,
0x7c, 0xaf, 0xce, 0x01, 0x17, 0x98, 0xcb, 0xbe, 0x06, 0x86, 0x3a, 0x13,
0x72, 0x4b, 0x7c, 0x81, 0x51, 0x24, 0x5d, 0xc3, 0xe9, 0xa2, 0x63, 0x1e,
0x4a, 0xeb, 0x66, 0xae, 0x01, 0x5e, 0xa4, 0xa4, 0x74, 0x9e, 0xee, 0x32,
0xe5, 0x59, 0x1b, 0x37, 0xef, 0x7d, 0xb3, 0x42, 0x8c, 0x93, 0x8b, 0xd3,
0x1e, 0x83, 0x43, 0xb5, 0x88, 0x3e, 0x24, 0xeb, 0xdc, 0x92, 0x2d, 0xcc,
0x9a, 0x9d, 0xf1, 0x7d, 0x16, 0x71, 0xcb, 0x25, 0x47, 0x36, 0xb0, 0xc4,
0x6b, 0xc8, 0x53, 0x4a, 0x25, 0x80, 0x47, 0x77, 0xdb, 0x97, 0x13, 0x15,
0x0f, 0x4a, 0xfa, 0x0c, 0x6c, 0x44, 0x13, 0x2f, 0xbc, 0x9a, 0x6b, 0x13,
0x57, 0xfc, 0x42, 0xb9, 0xe9, 0xd3, 0x2e, 0xd2, 0x11, 0xf4, 0xc5, 0x84,
0x55, 0xd2, 0xdf, 0x1d, 0xa7, 0x02, 0x81, 0x81, 0x00, 0xcb, 0xd7, 0xd6,
0x9d, 0x71, 0xb3, 0x86, 0xbe, 0x68, 0xed, 0x67, 0xe1, 0x51, 0x92, 0x17,
0x60, 0x58, 0xb3, 0x2a, 0x56, 0xfd, 0x18, 0xfb, 0x39, 0x4b, 0x14, 0xc6,
0xf6, 0x67, 0x0e, 0x31, 0xe3, 0xb3, 0x2f, 0x1f, 0xec, 0x16, 0x1c, 0x23,
0x2b, 0x60, 0x36, 0xd1, 0xcb, 0x4a, 0x03, 0x6a, 0x3a, 0x4c, 0x8c, 0xf2,
0x73, 0x08, 0x23, 0x29, 0xda, 0xcb, 0xf7, 0xb6, 0x18, 0x97, 0xc6, 0xfe,
0xd4, 0x40, 0x06, 0x87, 0x9d, 0x6e, 0xbb, 0x5d, 0x14, 0x44, 0xc8, 0x19,
0xfa, 0x7f, 0x0c, 0xc5, 0x02, 0x92, 0x00, 0xbb, 0x2e, 0x4f, 0x50, 0xb0,
0x71, 0x9f, 0xf3, 0x94, 0x12, 0xb8, 0x6c, 0x5f, 0xe1, 0x83, 0x7b, 0xbc,
0x8c, 0x0a, 0x6f, 0x09, 0x6a, 0x35, 0x4f, 0xf9, 0xa4, 0x92, 0x93, 0xe3,
0xad, 0x36, 0x25, 0x28, 0x90, 0x85, 0xd2, 0x9f, 0x86, 0xfd, 0xd9, 0xa8,
0x61, 0xe9, 0xb2, 0xec, 0x1f, 0x02, 0x81, 0x81, 0x00, 0xdd, 0x1c, 0x52,
0xda, 0x2b, 0xc2, 0x5a, 0x26, 0xb0, 0xcb, 0x0d, 0xae, 0xc7, 0xdb, 0xf0,
0x41, 0x75, 0x87, 0x4a, 0xe0, 0x1a, 0xdf, 0x53, 0xb9, 0xcf, 0xfe, 0x64,
0x4f, 0x6a, 0x70, 0x4d, 0x36, 0xbf, 0xb1, 0xa6, 0xf3, 0x5f, 0xf3, 0x5a,
0xa9, 0xe5, 0x8b, 0xea, 0x59, 0x5d, 0x6f, 0xf3, 0x87, 0xa9, 0xde, 0x11,
0x0c, 0x60, 0x64, 0x55, 0x9e, 0x5c, 0x1a, 0x91, 0x4e, 0x9c, 0x0d, 0xd5,
0xe9, 0x4a, 0x67, 0x9b, 0xe6, 0xfd, 0x03, 0x33, 0x2b, 0x74, 0xe3, 0xc3,
0x11, 0xc1, 0xe0, 0xf1, 0x4f, 0xdd, 0x13, 0x92, 0x16, 0x67, 0x4f, 0x6e,
0xc4, 0x8c, 0x0a, 0x48, 0x21, 0x92, 0x8f, 0xb2, 0xe5, 0xb5, 0x96, 0x5a,
0xb8, 0xc0, 0x67, 0xbb, 0xc8, 0x87, 0x2d, 0xa8, 0x4e, 0xd2, 0xd8, 0x05,
0xf0, 0xf0, 0xb3, 0x7c, 0x90, 0x98, 0x8f, 0x4f, 0x5d, 0x6c, 0xab, 0x71,
0x92, 0xe2, 0x88, 0xc8, 0xf3, 0x02, 0x81, 0x81, 0x00, 0x99, 0x27, 0x5a,
0x00, 0x81, 0x65, 0x39, 0x5f, 0xe6, 0xc6, 0x38, 0xbe, 0x79, 0xe3, 0x21,
0xdd, 0x29, 0xc7, 0xb3, 0x90, 0x18, 0x29, 0xa4, 0xd7, 0xaf, 0x29, 0xb5,
0x33, 0x7c, 0xca, 0x95, 0x81, 0x57, 0x27, 0x98, 0xfc, 0x70, 0xc0, 0x43,
0x4c, 0x5b, 0xc5, 0xd4, 0x6a, 0xc0, 0xf9, 0x3f, 0xde, 0xfd, 0x95, 0x08,
0xb4, 0x94, 0xf0, 0x96, 0x89, 0xe5, 0xa6, 0x00, 0x13, 0x0a, 0x36, 0x61,
0x50, 0x67, 0xaa, 0x80, 0x4a, 0x30, 0xe0, 0x65, 0x56, 0xcd, 0x36, 0xeb,
0x0d, 0xe2, 0x57, 0x5d, 0xce, 0x48, 0x94, 0x74, 0x0e, 0x9f, 0x59, 0x28,
0xb8, 0xb6, 0x4c, 0xf4, 0x7b, 0xfc, 0x44, 0xb0, 0xe5, 0x67, 0x3c, 0x98,
0xb5, 0x3f, 0x41, 0x9d, 0xf9, 0x46, 0x85, 0x08, 0x34, 0x36, 0x4d, 0x17,
0x4b, 0x14, 0xdb, 0x66, 0x56, 0xef, 0xb5, 0x08, 0x57, 0x0c, 0x73, 0x74,
0xa7, 0xdc, 0x46, 0xaa, 0x51, 0x02, 0x81, 0x80, 0x1e, 0x50, 0x4c, 0xde,
0x9c, 0x60, 0x6d, 0xd7, 0x31, 0xf6, 0xd8, 0x4f, 0xc2, 0x25, 0x7d, 0x83,
0xb3, 0xe7, 0xed, 0x92, 0xe7, 0x28, 0x1e, 0xb3, 0x9b, 0xcb, 0xf2, 0x86,
0xa4, 0x49, 0x45, 0x5e, 0xba, 0x1d, 0xdb, 0x21, 0x5d, 0xdf, 0xeb, 0x3c,
0x5e, 0x01, 0xc6, 0x68, 0x25, 0x28, 0xe6, 0x1a, 0xbf, 0xc1, 0xa1, 0xc5,
0x92, 0x0b, 0x08, 0x43, 0x0e, 0x5a, 0xa3, 0x85, 0x8a, 0x65, 0xb4, 0x54,
0xa1, 0x4c, 0x20, 0xa2, 0x5a, 0x08, 0xf6, 0x90, 0x0d, 0x9a, 0xd7, 0x20,
0xf1, 0x10, 0x66, 0x28, 0x4c, 0x22, 0x56, 0xa6, 0xb9, 0xff, 0xd0, 0x6a,
0x62, 0x8c, 0x9f, 0xf8, 0x7c, 0xf4, 0xad, 0xd7, 0xe8, 0xf9, 0x87, 0x43,
0xbf, 0x73, 0x5b, 0x04, 0xc7, 0xd0, 0x77, 0xcc, 0xe3, 0xbe, 0xda, 0xc2,
0x07, 0xed, 0x8d, 0x2a, 0x15, 0x77, 0x1d, 0x53, 0x47, 0xe0, 0xa2, 0x11,
0x41, 0x0d, 0xe2, 0xe7,
};
/* The matching public key used for encryption*/
static const unsigned char pub_key_der[] = {
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc2, 0x44, 0xbc,
0xcf, 0x5b, 0xca, 0xcd, 0x80, 0x77, 0xae, 0xf9, 0x7a, 0x34, 0xbb, 0x37,
0x6f, 0x5c, 0x76, 0x4c, 0xe4, 0xbb, 0x0c, 0x1d, 0xe7, 0xfe, 0x0f, 0xda,
0xcf, 0x8c, 0x56, 0x65, 0x72, 0x6e, 0x2c, 0xf9, 0xfd, 0x87, 0x43, 0xeb,
0x4c, 0x26, 0xb1, 0xd3, 0xf0, 0x87, 0xb1, 0x18, 0x68, 0x14, 0x7d, 0x3c,
0x2a, 0xfa, 0xc2, 0x5d, 0x70, 0x19, 0x11, 0x00, 0x2e, 0xb3, 0x9c, 0x8e,
0x38, 0x08, 0xbe, 0xe3, 0xeb, 0x7d, 0x6e, 0xc7, 0x19, 0xc6, 0x7f, 0x59,
0x48, 0x84, 0x1b, 0xe3, 0x27, 0x30, 0x46, 0x30, 0xd3, 0xfc, 0xfc, 0xb3,
0x35, 0x75, 0xc4, 0x31, 0x1a, 0xc0, 0xc2, 0x4c, 0x0b, 0xc7, 0x01, 0x95,
0xb2, 0xdc, 0x17, 0x77, 0x9b, 0x09, 0x15, 0x04, 0xbc, 0xdb, 0x57, 0x0b,
0x26, 0xda, 0x59, 0x54, 0x0d, 0x6e, 0xb7, 0x89, 0xbc, 0x53, 0x9d, 0x5f,
0x8c, 0xad, 0x86, 0x97, 0xd2, 0x48, 0x4f, 0x5c, 0x94, 0xdd, 0x30, 0x2f,
0xcf, 0xfc, 0xde, 0x20, 0x31, 0x25, 0x9d, 0x29, 0x25, 0x78, 0xb7, 0xd2,
0x5b, 0x5d, 0x99, 0x5b, 0x08, 0x12, 0x81, 0x79, 0x89, 0xa0, 0xcf, 0x8f,
0x40, 0xb1, 0x77, 0x72, 0x3b, 0x13, 0xfc, 0x55, 0x43, 0x70, 0x29, 0xd5,
0x41, 0xed, 0x31, 0x4b, 0x2d, 0x6c, 0x7d, 0xcf, 0x99, 0x5f, 0xd1, 0x72,
0x9f, 0x8b, 0x32, 0x96, 0xde, 0x5d, 0x8b, 0x19, 0x77, 0x75, 0xff, 0x09,
0xbf, 0x26, 0xe9, 0xd7, 0x3d, 0xc7, 0x1a, 0x81, 0xcf, 0x05, 0x1b, 0x89,
0xbf, 0x45, 0x32, 0xbf, 0x5e, 0xc9, 0xe3, 0x5c, 0x33, 0x4a, 0x72, 0x47,
0xf4, 0x24, 0xae, 0x9b, 0x38, 0x24, 0x76, 0x9a, 0xa2, 0x9a, 0x50, 0x50,
0x49, 0xf5, 0x26, 0xb9, 0x55, 0xa6, 0x47, 0xc9, 0x14, 0xa2, 0xca, 0xd4,
0xa8, 0x8a, 0x9f, 0xe9, 0x5a, 0x5a, 0x12, 0xaa, 0x30, 0xd5, 0x78, 0x8b,
0x39, 0x02, 0x03, 0x01, 0x00, 0x01,
};

View File

@@ -0,0 +1,42 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto and libssl are on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./tls-client-block www.example.com 443
TESTS = tls-client-block \
tls-server-block \
quic-client-block \
quic-multi-stream \
tls-client-non-block \
quic-client-non-block
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto -lssl
all: $(TESTS) chain
tls-client-block: tls-client-block.o
tls-server-block: tls-server-block.o
quic-client-block: quic-client-block.o
quic-multi-stream: quic-multi-stream.o
tls-client-non-block: tls-client-non-block.o
quic-client-non-block: quic-client-non-block.o
chain: chain.pem
pkey.pem:
openssl genpkey -algorithm rsa -out pkey.pem -pkeyopt rsa_keygen_bits:2048
chain.pem: pkey.pem
openssl req -x509 -new -key pkey.pem -days 36500 -subj / -out chain.pem
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) $(TESTS) *.o
.PHONY: test chain
test: all
@echo "\nTLS and QUIC tests:"
@echo "skipped"

View File

@@ -0,0 +1,77 @@
The OpenSSL Guide Demos
=======================
The demos in this directory are the complete source code for the applications
developed in the OpenSSL Guide tutorials. Refer to the various tutorial pages in
the [guide] for an extensive discussion on the demos available here.
They must be built before they can be run. An example UNIX style Makefile is
supplied. Just type "make" from this directory on a Linux/UNIX system.
Running the TLS Demos
---------------------
To run the demos when linked with a shared library (default) ensure that
libcrypto and libssl are on the library path. For example, assuming you have
already built OpenSSL from this source and in the default location then to run
the tls-client-block demo do this:
LD_LIBRARY_PATH=../.. ./tls-client-block hostname port
In the above replace "hostname" and "port" with the hostname and the port number
of the server you are connecting to.
The above assumes that your default trusted certificate store containing trusted
CA certificates has been properly setup and configured as described on the
[TLS Introduction] page.
You can run a test server to try out these demos using the "openssl s_server"
command line utility and using the test server certificate and key provided in
this directory. For example:
LD_LIBRARY_PATH=../.. ../../apps/openssl s_server -www -accept localhost:4443 -cert servercert.pem -key serverkey.pem
The test server certificate in this directory will use a CA that will not be in
your default trusted certificate store. The CA certificate to use is also
available in this directory. To use it you can override the default trusted
certificate store like this:
SSL_CERT_FILE=rootcert.pem LD_LIBRARY_PATH=../.. ./tls-client-block localhost 4443
If the above command is successful it will connect to the test "s_server" and
send a simple HTTP request to it. The server will respond with a page of
information giving details about the TLS connection that was used.
Note that the test server certificate used here is only suitable for use on
"localhost".
The tls-client-non-block demo can be run in exactly the same way. Just replace
"tls-client-block" in the above example commands with "tls-client-non-block".
Running the QUIC Demos
----------------------
The QUIC demos can be run in a very similar way to the TLS demos. However, a
different server implementation will need to be used.
The OpenSSL source distribution includes a test QUIC server implementation for
use with the demos. Note that, although this server does get built when building
OpenSSL from source, it does not get installed via "make install". After
building OpenSSL from source you will find the "quicserver" utility in the
"util" sub-directory of the top of the build tree. This server utility is not
suitable for production use and exists for test purposes only. It will be
removed from a future version of OpenSSL.
While in the demos directory the quic server can be run like this:
./../util/quicserver localhost 4443 servercert.pem serverkey.pem
The QUIC demos can then be run in the same was as the TLS demos. For example
to run the quic-client-block demo:
SSL_CERT_FILE=rootcert.pem LD_LIBRARY_PATH=../.. ./quic-client-block localhost 4443
<!-- Links -->
[guide]: https://www.openssl.org/docs/manmaster/man7/ossl-guide-introduction.html
[TLS Introduction]: https://www.openssl.org/docs/manmaster/man7/ossl-guide-tls-introduction.html

View File

@@ -0,0 +1,31 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto and libssl are on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./tls-client-block www.example.com 443
PROGRAMS{noinst} = tls-client-block \
quic-client-block \
quic-multi-stream \
tls-client-non-block \
quic-client-non-block
INCLUDE[tls-client-block]=../../include
SOURCE[tls-client-block]=tls-client-block.c
DEPEND[tls-client-block]=../../libcrypto ../../libssl
INCLUDE[quic-client-block]=../../include
SOURCE[quic-client-block]=quic-client-block.c
DEPEND[quic-client-block]=../../libcrypto ../../libssl
INCLUDE[quic-multi-stream]=../../include
SOURCE[quic-multi-stream]=quic-multi-stream.c
DEPEND[quic-multi-stream]=../../libcrypto ../../libssl
INCLUDE[tls-client-non-block]=../../include
SOURCE[tls-client-non-block]=tls-client-non-block.c
DEPEND[tls-client-non-block]=../../libcrypto ../../libssl
INCLUDE[quic-client-non-block]=../../include
SOURCE[quic-client-non-block]=quic-client-non-block.c
DEPEND[quic-client-non-block]=../../libcrypto ../../libssl

View File

@@ -0,0 +1,341 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-quic-client-block.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_DGRAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Helper function to create a BIO connected to the server */
static BIO *create_socket_bio(const char *hostname, const char *port,
int family, BIO_ADDR **peer_addr)
{
int sock = -1;
BIO_ADDRINFO *res;
const BIO_ADDRINFO *ai = NULL;
BIO *bio;
/*
* Lookup IP address info for the server.
*/
if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,
&res))
return NULL;
/*
* Loop through all the possible addresses for the server and find one
* we can connect to.
*/
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/*
* Create a UDP socket. We could equally use non-OpenSSL calls such
* as "socket" here for this and the subsequent connect and close
* functions. But for portability reasons and also so that we get
* errors on the OpenSSL stack in the event of a failure we use
* OpenSSL's versions of these functions.
*/
sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
if (sock == -1)
continue;
/* Connect the socket to the server's address */
if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
/* Set to nonblocking mode */
if (!BIO_socket_nbio(sock, 1)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
break;
}
if (sock != -1) {
*peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
if (*peer_addr == NULL) {
BIO_closesocket(sock);
return NULL;
}
}
/* Free the address information resources we allocated earlier */
BIO_ADDRINFO_free(res);
/* If sock is -1 then we've been unable to connect to the server */
if (sock == -1)
return NULL;
/* Create a BIO to wrap the socket */
bio = BIO_new(BIO_s_datagram());
if (bio == NULL) {
BIO_closesocket(sock);
return NULL;
}
/*
* Associate the newly created BIO with the underlying socket. By
* passing BIO_CLOSE here the socket will be automatically closed when
* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
* case you must close the socket explicitly when it is no longer
* needed.
*/
BIO_set_fd(bio, sock, BIO_CLOSE);
return bio;
}
/*
* Simple application to send a basic HTTP/1.0 request to a server and
* print the response on the screen. Note that HTTP/1.0 over QUIC is
* non-standard and will not typically be supported by real world servers. This
* is for demonstration purposes only.
*/
int main(int argc, char *argv[])
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
BIO *bio = NULL;
int res = EXIT_FAILURE;
int ret;
unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
const char *request_end = "\r\n\r\n";
size_t written, readbytes;
char buf[160];
BIO_ADDR *peer_addr = NULL;
char *hostname, *port;
int argnext = 1;
int ipv6 = 0;
if (argc < 3) {
printf("Usage: quic-client-block [-6] hostname port\n");
goto end;
}
if (!strcmp(argv[argnext], "-6")) {
if (argc < 4) {
printf("Usage: quic-client-block [-6] hostname port\n");
goto end;
}
ipv6 = 1;
argnext++;
}
hostname = argv[argnext++];
port = argv[argnext];
/*
* Create an SSL_CTX which we can use to create SSL objects from. We
* want an SSL_CTX for creating clients so we use
* OSSL_QUIC_client_method() here.
*/
ctx = SSL_CTX_new(OSSL_QUIC_client_method());
if (ctx == NULL) {
printf("Failed to create the SSL_CTX\n");
goto end;
}
/*
* Configure the client to abort the handshake if certificate
* verification fails. Virtually all clients should do this unless you
* really know what you are doing.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Use the default trusted certificate store */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
printf("Failed to set the default trusted certificate store\n");
goto end;
}
/* Create an SSL object to represent the TLS connection */
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create the SSL object\n");
goto end;
}
/*
* Create the underlying transport socket/BIO and associate it with the
* connection.
*/
bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET, &peer_addr);
if (bio == NULL) {
printf("Failed to crete the BIO\n");
goto end;
}
SSL_set_bio(ssl, bio, bio);
/*
* Tell the server during the handshake which hostname we are attempting
* to connect to in case the server supports multiple hosts.
*/
if (!SSL_set_tlsext_host_name(ssl, hostname)) {
printf("Failed to set the SNI hostname\n");
goto end;
}
/*
* Ensure we check during certificate verification that the server has
* supplied a certificate for the hostname that we were expecting.
* Virtually all clients should do this unless you really know what you
* are doing.
*/
if (!SSL_set1_host(ssl, hostname)) {
printf("Failed to set the certificate verification hostname");
goto end;
}
/* SSL_set_alpn_protos returns 0 for success! */
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
printf("Failed to set the ALPN for the connection\n");
goto end;
}
/* Set the IP address of the remote peer */
if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
printf("Failed to set the initial peer address\n");
goto end;
}
/* Do the handshake with the server */
if (SSL_connect(ssl) < 1) {
printf("Failed to connect to the server\n");
/*
* If the failure is due to a verification error we can get more
* information about it from SSL_get_verify_result().
*/
if (SSL_get_verify_result(ssl) != X509_V_OK)
printf("Verify error: %s\n",
X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
goto end;
}
/* Write an HTTP GET request to the peer */
if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
printf("Failed to write start of HTTP request\n");
goto end;
}
if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
printf("Failed to write hostname in HTTP request\n");
goto end;
}
if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
printf("Failed to write end of HTTP request\n");
goto end;
}
/*
* Get up to sizeof(buf) bytes of the response. We keep reading until the
* server closes the connection.
*/
while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
/*
* OpenSSL does not guarantee that the returned data is a string or
* that it is NUL terminated so we use fwrite() to write the exact
* number of bytes that we read. The data could be non-printable or
* have NUL characters in the middle of it. For this simple example
* we're going to print it to stdout anyway.
*/
fwrite(buf, 1, readbytes, stdout);
}
/* In case the response didn't finish with a newline we add one now */
printf("\n");
/*
* Check whether we finished the while loop above normally or as the
* result of an error. The 0 argument to SSL_get_error() is the return
* code we received from the SSL_read_ex() call. It must be 0 in order
* to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In
* QUIC terms this means that the peer has sent FIN on the stream to
* indicate that no further data will be sent.
*/
switch (SSL_get_error(ssl, 0)) {
case SSL_ERROR_ZERO_RETURN:
/* Normal completion of the stream */
break;
case SSL_ERROR_SSL:
/*
* Some stream fatal error occurred. This could be because of a stream
* reset - or some failure occurred on the underlying connection.
*/
switch (SSL_get_stream_read_state(ssl)) {
case SSL_STREAM_STATE_RESET_REMOTE:
printf("Stream reset occurred\n");
/* The stream has been reset but the connection is still healthy. */
break;
case SSL_STREAM_STATE_CONN_CLOSED:
printf("Connection closed\n");
/* Connection is already closed. Skip SSL_shutdown() */
goto end;
default:
printf("Unknown stream failure\n");
break;
}
break;
default:
/* Some other unexpected error occurred */
printf ("Failed reading remaining data\n");
break;
}
/*
* Repeatedly call SSL_shutdown() until the connection is fully
* closed.
*/
do {
ret = SSL_shutdown(ssl);
if (ret < 0) {
printf("Error shutting down: %d\n", ret);
goto end;
}
} while (ret != 1);
/* Success! */
res = EXIT_SUCCESS;
end:
/*
* If something bad happened then we will dump the contents of the
* OpenSSL error stack to stderr. There might be some useful diagnostic
* information there.
*/
if (res == EXIT_FAILURE)
ERR_print_errors_fp(stderr);
/*
* Free the resources we allocated. We do not free the BIO object here
* because ownership of it was immediately transferred to the SSL object
* via SSL_set_bio(). The BIO will be freed when we free the SSL object.
*/
SSL_free(ssl);
SSL_CTX_free(ctx);
BIO_ADDR_free(peer_addr);
return res;
}

View File

@@ -0,0 +1,431 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-quic-client-non-block.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_DGRAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
# include <sys/select.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Helper function to create a BIO connected to the server */
static BIO *create_socket_bio(const char *hostname, const char *port,
int family, BIO_ADDR **peer_addr)
{
int sock = -1;
BIO_ADDRINFO *res;
const BIO_ADDRINFO *ai = NULL;
BIO *bio;
/*
* Lookup IP address info for the server.
*/
if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,
&res))
return NULL;
/*
* Loop through all the possible addresses for the server and find one
* we can connect to.
*/
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/*
* Create a UDP socket. We could equally use non-OpenSSL calls such
* as "socket" here for this and the subsequent connect and close
* functions. But for portability reasons and also so that we get
* errors on the OpenSSL stack in the event of a failure we use
* OpenSSL's versions of these functions.
*/
sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
if (sock == -1)
continue;
/* Connect the socket to the server's address */
if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
/* Set to nonblocking mode */
if (!BIO_socket_nbio(sock, 1)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
break;
}
if (sock != -1) {
*peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
if (*peer_addr == NULL) {
BIO_closesocket(sock);
return NULL;
}
}
/* Free the address information resources we allocated earlier */
BIO_ADDRINFO_free(res);
/* If sock is -1 then we've been unable to connect to the server */
if (sock == -1)
return NULL;
/* Create a BIO to wrap the socket */
bio = BIO_new(BIO_s_datagram());
if (bio == NULL) {
BIO_closesocket(sock);
return NULL;
}
/*
* Associate the newly created BIO with the underlying socket. By
* passing BIO_CLOSE here the socket will be automatically closed when
* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
* case you must close the socket explicitly when it is no longer
* needed.
*/
BIO_set_fd(bio, sock, BIO_CLOSE);
return bio;
}
static void wait_for_activity(SSL *ssl)
{
fd_set wfds, rfds;
int width, sock, isinfinite;
struct timeval tv;
struct timeval *tvp = NULL;
/* Get hold of the underlying file descriptor for the socket */
sock = SSL_get_fd(ssl);
FD_ZERO(&wfds);
FD_ZERO(&rfds);
/*
* Find out if we would like to write to the socket, or read from it (or
* both)
*/
if (SSL_net_write_desired(ssl))
FD_SET(sock, &wfds);
if (SSL_net_read_desired(ssl))
FD_SET(sock, &rfds);
width = sock + 1;
/*
* Find out when OpenSSL would next like to be called, regardless of
* whether the state of the underlying socket has changed or not.
*/
if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite)
tvp = &tv;
/*
* Wait until the socket is writeable or readable. We use select here
* for the sake of simplicity and portability, but you could equally use
* poll/epoll or similar functions
*
* NOTE: For the purposes of this demonstration code this effectively
* makes this demo block until it has something more useful to do. In a
* real application you probably want to go and do other work here (e.g.
* update a GUI, or service other connections).
*
* Let's say for example that you want to update the progress counter on
* a GUI every 100ms. One way to do that would be to use the timeout in
* the last parameter to "select" below. If the tvp value is greater
* than 100ms then use 100ms instead. Then, when select returns, you
* check if it did so because of activity on the file descriptors or
* because of the timeout. If the 100ms GUI timeout has expired but the
* tvp timeout has not then go and update the GUI and then restart the
* "select" (with updated timeouts).
*/
select(width, &rfds, &wfds, NULL, tvp);
}
static int handle_io_failure(SSL *ssl, int res)
{
switch (SSL_get_error(ssl, res)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
/* Temporary failure. Wait until we can read/write and try again */
wait_for_activity(ssl);
return 1;
case SSL_ERROR_ZERO_RETURN:
/* EOF */
return 0;
case SSL_ERROR_SYSCALL:
return -1;
case SSL_ERROR_SSL:
/*
* Some stream fatal error occurred. This could be because of a
* stream reset - or some failure occurred on the underlying
* connection.
*/
switch (SSL_get_stream_read_state(ssl)) {
case SSL_STREAM_STATE_RESET_REMOTE:
printf("Stream reset occurred\n");
/*
* The stream has been reset but the connection is still
* healthy.
*/
break;
case SSL_STREAM_STATE_CONN_CLOSED:
printf("Connection closed\n");
/* Connection is already closed. */
break;
default:
printf("Unknown stream failure\n");
break;
}
/*
* If the failure is due to a verification error we can get more
* information about it from SSL_get_verify_result().
*/
if (SSL_get_verify_result(ssl) != X509_V_OK)
printf("Verify error: %s\n",
X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
return -1;
default:
return -1;
}
}
/*
* Simple application to send a basic HTTP/1.0 request to a server and
* print the response on the screen. Note that HTTP/1.0 over QUIC is
* non-standard and will not typically be supported by real world servers. This
* is for demonstration purposes only.
*/
int main(int argc, char *argv[])
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
BIO *bio = NULL;
int res = EXIT_FAILURE;
int ret;
unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
const char *request_end = "\r\n\r\n";
size_t written, readbytes = 0;
char buf[160];
BIO_ADDR *peer_addr = NULL;
int eof = 0;
char *hostname, *port;
int ipv6 = 0;
int argnext = 1;
if (argc < 3) {
printf("Usage: quic-client-non-block [-6] hostname port\n");
goto end;
}
if (!strcmp(argv[argnext], "-6")) {
if (argc < 4) {
printf("Usage: quic-client-non-block [-6] hostname port\n");
goto end;
}
ipv6 = 1;
argnext++;
}
hostname = argv[argnext++];
port = argv[argnext];
/*
* Create an SSL_CTX which we can use to create SSL objects from. We
* want an SSL_CTX for creating clients so we use
* OSSL_QUIC_client_method() here.
*/
ctx = SSL_CTX_new(OSSL_QUIC_client_method());
if (ctx == NULL) {
printf("Failed to create the SSL_CTX\n");
goto end;
}
/*
* Configure the client to abort the handshake if certificate
* verification fails. Virtually all clients should do this unless you
* really know what you are doing.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Use the default trusted certificate store */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
printf("Failed to set the default trusted certificate store\n");
goto end;
}
/* Create an SSL object to represent the TLS connection */
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create the SSL object\n");
goto end;
}
/*
* Create the underlying transport socket/BIO and associate it with the
* connection.
*/
bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET,
&peer_addr);
if (bio == NULL) {
printf("Failed to crete the BIO\n");
goto end;
}
SSL_set_bio(ssl, bio, bio);
/*
* Tell the server during the handshake which hostname we are attempting
* to connect to in case the server supports multiple hosts.
*/
if (!SSL_set_tlsext_host_name(ssl, hostname)) {
printf("Failed to set the SNI hostname\n");
goto end;
}
/*
* Ensure we check during certificate verification that the server has
* supplied a certificate for the hostname that we were expecting.
* Virtually all clients should do this unless you really know what you
* are doing.
*/
if (!SSL_set1_host(ssl, hostname)) {
printf("Failed to set the certificate verification hostname");
goto end;
}
/* SSL_set_alpn_protos returns 0 for success! */
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
printf("Failed to set the ALPN for the connection\n");
goto end;
}
/* Set the IP address of the remote peer */
if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
printf("Failed to set the initial peer address\n");
goto end;
}
/*
* The underlying socket is always nonblocking with QUIC, but the default
* behaviour of the SSL object is still to block. We set it for nonblocking
* mode in this demo.
*/
if (!SSL_set_blocking_mode(ssl, 0)) {
printf("Failed to turn off blocking mode\n");
goto end;
}
/* Do the handshake with the server */
while ((ret = SSL_connect(ssl)) != 1) {
if (handle_io_failure(ssl, ret) == 1)
continue; /* Retry */
printf("Failed to connect to server\n");
goto end; /* Cannot retry: error */
}
/* Write an HTTP GET request to the peer */
while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write start of HTTP request\n");
goto end; /* Cannot retry: error */
}
while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write hostname in HTTP request\n");
goto end; /* Cannot retry: error */
}
while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write end of HTTP request\n");
goto end; /* Cannot retry: error */
}
do {
/*
* Get up to sizeof(buf) bytes of the response. We keep reading until
* the server closes the connection.
*/
while (!eof && !SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
switch (handle_io_failure(ssl, 0)) {
case 1:
continue; /* Retry */
case 0:
eof = 1;
continue;
case -1:
default:
printf("Failed reading remaining data\n");
goto end; /* Cannot retry: error */
}
}
/*
* OpenSSL does not guarantee that the returned data is a string or
* that it is NUL terminated so we use fwrite() to write the exact
* number of bytes that we read. The data could be non-printable or
* have NUL characters in the middle of it. For this simple example
* we're going to print it to stdout anyway.
*/
if (!eof)
fwrite(buf, 1, readbytes, stdout);
} while (!eof);
/* In case the response didn't finish with a newline we add one now */
printf("\n");
/*
* Repeatedly call SSL_shutdown() until the connection is fully
* closed.
*/
while ((ret = SSL_shutdown(ssl)) != 1) {
if (ret < 0 && handle_io_failure(ssl, ret) == 1)
continue; /* Retry */
}
/* Success! */
res = EXIT_SUCCESS;
end:
/*
* If something bad happened then we will dump the contents of the
* OpenSSL error stack to stderr. There might be some useful diagnostic
* information there.
*/
if (res == EXIT_FAILURE)
ERR_print_errors_fp(stderr);
/*
* Free the resources we allocated. We do not free the BIO object here
* because ownership of it was immediately transferred to the SSL object
* via SSL_set_bio(). The BIO will be freed when we free the SSL object.
*/
SSL_free(ssl);
SSL_CTX_free(ctx);
BIO_ADDR_free(peer_addr);
return res;
}

View File

@@ -0,0 +1,444 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-quic-multi-stream.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_DGRAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Helper function to create a BIO connected to the server */
static BIO *create_socket_bio(const char *hostname, const char *port,
int family, BIO_ADDR **peer_addr)
{
int sock = -1;
BIO_ADDRINFO *res;
const BIO_ADDRINFO *ai = NULL;
BIO *bio;
/*
* Lookup IP address info for the server.
*/
if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,
&res))
return NULL;
/*
* Loop through all the possible addresses for the server and find one
* we can connect to.
*/
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/*
* Create a UDP socket. We could equally use non-OpenSSL calls such
* as "socket" here for this and the subsequent connect and close
* functions. But for portability reasons and also so that we get
* errors on the OpenSSL stack in the event of a failure we use
* OpenSSL's versions of these functions.
*/
sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
if (sock == -1)
continue;
/* Connect the socket to the server's address */
if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
/* Set to nonblocking mode */
if (!BIO_socket_nbio(sock, 1)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
break;
}
if (sock != -1) {
*peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
if (*peer_addr == NULL) {
BIO_closesocket(sock);
return NULL;
}
}
/* Free the address information resources we allocated earlier */
BIO_ADDRINFO_free(res);
/* If sock is -1 then we've been unable to connect to the server */
if (sock == -1)
return NULL;
/* Create a BIO to wrap the socket */
bio = BIO_new(BIO_s_datagram());
if (bio == NULL) {
BIO_closesocket(sock);
return NULL;
}
/*
* Associate the newly created BIO with the underlying socket. By
* passing BIO_CLOSE here the socket will be automatically closed when
* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
* case you must close the socket explicitly when it is no longer
* needed.
*/
BIO_set_fd(bio, sock, BIO_CLOSE);
return bio;
}
static int write_a_request(SSL *stream, const char *request_start,
const char *hostname)
{
const char *request_end = "\r\n\r\n";
size_t written;
if (!SSL_write_ex(stream, request_start, strlen(request_start),
&written))
return 0;
if (!SSL_write_ex(stream, hostname, strlen(hostname), &written))
return 0;
if (!SSL_write_ex(stream, request_end, strlen(request_end), &written))
return 0;
return 1;
}
/*
* Simple application to send basic HTTP/1.0 requests to a server and print the
* response on the screen. Note that HTTP/1.0 over QUIC is not a real protocol
* and will not be supported by real world servers. This is for demonstration
* purposes only.
*/
int main(int argc, char *argv[])
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
SSL *stream1 = NULL, *stream2 = NULL, *stream3 = NULL;
BIO *bio = NULL;
int res = EXIT_FAILURE;
int ret;
unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
const char *request1_start =
"GET /request1.html HTTP/1.0\r\nConnection: close\r\nHost: ";
const char *request2_start =
"GET /request2.html HTTP/1.0\r\nConnection: close\r\nHost: ";
size_t readbytes;
char buf[160];
BIO_ADDR *peer_addr = NULL;
char *hostname, *port;
int argnext = 1;
int ipv6 = 0;
if (argc < 3) {
printf("Usage: quic-client-non-block [-6] hostname port\n");
goto end;
}
if (!strcmp(argv[argnext], "-6")) {
if (argc < 4) {
printf("Usage: quic-client-non-block [-6] hostname port\n");
goto end;
}
ipv6 = 1;
argnext++;
}
hostname = argv[argnext++];
port = argv[argnext];
/*
* Create an SSL_CTX which we can use to create SSL objects from. We
* want an SSL_CTX for creating clients so we use
* OSSL_QUIC_client_method() here.
*/
ctx = SSL_CTX_new(OSSL_QUIC_client_method());
if (ctx == NULL) {
printf("Failed to create the SSL_CTX\n");
goto end;
}
/*
* Configure the client to abort the handshake if certificate
* verification fails. Virtually all clients should do this unless you
* really know what you are doing.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Use the default trusted certificate store */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
printf("Failed to set the default trusted certificate store\n");
goto end;
}
/* Create an SSL object to represent the TLS connection */
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create the SSL object\n");
goto end;
}
/*
* We will use multiple streams so we will disable the default stream mode.
* This is not a requirement for using multiple streams but is recommended.
*/
if (!SSL_set_default_stream_mode(ssl, SSL_DEFAULT_STREAM_MODE_NONE)) {
printf("Failed to disable the default stream mode\n");
goto end;
}
/*
* Create the underlying transport socket/BIO and associate it with the
* connection.
*/
bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET, &peer_addr);
if (bio == NULL) {
printf("Failed to crete the BIO\n");
goto end;
}
SSL_set_bio(ssl, bio, bio);
/*
* Tell the server during the handshake which hostname we are attempting
* to connect to in case the server supports multiple hosts.
*/
if (!SSL_set_tlsext_host_name(ssl, hostname)) {
printf("Failed to set the SNI hostname\n");
goto end;
}
/*
* Ensure we check during certificate verification that the server has
* supplied a certificate for the hostname that we were expecting.
* Virtually all clients should do this unless you really know what you
* are doing.
*/
if (!SSL_set1_host(ssl, hostname)) {
printf("Failed to set the certificate verification hostname");
goto end;
}
/* SSL_set_alpn_protos returns 0 for success! */
if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
printf("Failed to set the ALPN for the connection\n");
goto end;
}
/* Set the IP address of the remote peer */
if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
printf("Failed to set the initial peer address\n");
goto end;
}
/* Do the handshake with the server */
if (SSL_connect(ssl) < 1) {
printf("Failed to connect to the server\n");
/*
* If the failure is due to a verification error we can get more
* information about it from SSL_get_verify_result().
*/
if (SSL_get_verify_result(ssl) != X509_V_OK)
printf("Verify error: %s\n",
X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
goto end;
}
/*
* We create two new client initiated streams. The first will be
* bi-directional, and the second will be uni-directional.
*/
stream1 = SSL_new_stream(ssl, 0);
stream2 = SSL_new_stream(ssl, SSL_STREAM_FLAG_UNI);
if (stream1 == NULL || stream2 == NULL) {
printf("Failed to create streams\n");
goto end;
}
/* Write an HTTP GET request on each of our streams to the peer */
if (!write_a_request(stream1, request1_start, hostname)) {
printf("Failed to write HTTP request on stream 1\n");
goto end;
}
if (!write_a_request(stream2, request2_start, hostname)) {
printf("Failed to write HTTP request on stream 2\n");
goto end;
}
/*
* In this demo we read all the data from one stream before reading all the
* data from the next stream for simplicity. In practice there is no need to
* do this. We can interleave IO on the different streams if we wish, or
* manage the streams entirely separately on different threads.
*/
printf("Stream 1 data:\n");
/*
* Get up to sizeof(buf) bytes of the response from stream 1 (which is a
* bidirectional stream). We keep reading until the server closes the
* connection.
*/
while (SSL_read_ex(stream1, buf, sizeof(buf), &readbytes)) {
/*
* OpenSSL does not guarantee that the returned data is a string or
* that it is NUL terminated so we use fwrite() to write the exact
* number of bytes that we read. The data could be non-printable or
* have NUL characters in the middle of it. For this simple example
* we're going to print it to stdout anyway.
*/
fwrite(buf, 1, readbytes, stdout);
}
/* In case the response didn't finish with a newline we add one now */
printf("\n");
/*
* Check whether we finished the while loop above normally or as the
* result of an error. The 0 argument to SSL_get_error() is the return
* code we received from the SSL_read_ex() call. It must be 0 in order
* to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In
* QUIC terms this means that the peer has sent FIN on the stream to
* indicate that no further data will be sent.
*/
switch (SSL_get_error(stream1, 0)) {
case SSL_ERROR_ZERO_RETURN:
/* Normal completion of the stream */
break;
case SSL_ERROR_SSL:
/*
* Some stream fatal error occurred. This could be because of a stream
* reset - or some failure occurred on the underlying connection.
*/
switch (SSL_get_stream_read_state(stream1)) {
case SSL_STREAM_STATE_RESET_REMOTE:
printf("Stream reset occurred\n");
/* The stream has been reset but the connection is still healthy. */
break;
case SSL_STREAM_STATE_CONN_CLOSED:
printf("Connection closed\n");
/* Connection is already closed. Skip SSL_shutdown() */
goto end;
default:
printf("Unknown stream failure\n");
break;
}
break;
default:
/* Some other unexpected error occurred */
printf ("Failed reading remaining data\n");
break;
}
/*
* In our hypothetical HTTP/1.0 over QUIC protocol that we are using we
* assume that the server will respond with a server initiated stream
* containing the data requested in our uni-directional stream. This doesn't
* really make sense to do in a real protocol, but its just for
* demonstration purposes.
*
* We're using blocking mode so this will block until a stream becomes
* available. We could override this behaviour if we wanted to by setting
* the SSL_ACCEPT_STREAM_NO_BLOCK flag in the second argument below.
*/
stream3 = SSL_accept_stream(ssl, 0);
if (stream3 == NULL) {
printf("Failed to accept a new stream\n");
goto end;
}
printf("Stream 3 data:\n");
/*
* Read the data from stream 3 like we did for stream 1 above. Note that
* stream 2 was uni-directional so there is no data to be read from that
* one.
*/
while (SSL_read_ex(stream3, buf, sizeof(buf), &readbytes))
fwrite(buf, 1, readbytes, stdout);
printf("\n");
/* Check for errors on the stream */
switch (SSL_get_error(stream3, 0)) {
case SSL_ERROR_ZERO_RETURN:
/* Normal completion of the stream */
break;
case SSL_ERROR_SSL:
switch (SSL_get_stream_read_state(stream3)) {
case SSL_STREAM_STATE_RESET_REMOTE:
printf("Stream reset occurred\n");
break;
case SSL_STREAM_STATE_CONN_CLOSED:
printf("Connection closed\n");
goto end;
default:
printf("Unknown stream failure\n");
break;
}
break;
default:
printf ("Failed reading remaining data\n");
break;
}
/*
* Repeatedly call SSL_shutdown() until the connection is fully
* closed.
*/
do {
ret = SSL_shutdown(ssl);
if (ret < 0) {
printf("Error shutting down: %d\n", ret);
goto end;
}
} while (ret != 1);
/* Success! */
res = EXIT_SUCCESS;
end:
/*
* If something bad happened then we will dump the contents of the
* OpenSSL error stack to stderr. There might be some useful diagnostic
* information there.
*/
if (res == EXIT_FAILURE)
ERR_print_errors_fp(stderr);
/*
* Free the resources we allocated. We do not free the BIO object here
* because ownership of it was immediately transferred to the SSL object
* via SSL_set_bio(). The BIO will be freed when we free the SSL object.
*/
SSL_free(ssl);
SSL_free(stream1);
SSL_free(stream2);
SSL_free(stream3);
SSL_CTX_free(ctx);
BIO_ADDR_free(peer_addr);
return res;
}

View File

@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC8TCCAdmgAwIBAgIBATANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTE2MDExNDIyMjkwNVoYDzIxMTYwMTE1MjIyOTA1WjASMRAwDgYDVQQD
DAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv5oV1s3N
us7SINg7omu5AxueEgK97mh5PU3hgZpliSFaESmL2qLGeP609oXs/68XDXVW4utU
LCOjLh0np+5Xy3i3GRDXgBZ72QDe23WqqQqqaBlQVVm1WxG+amRtZJEWdSIsiFBt
k+8dBElHh2WQDhDOWqHGHQarQgJPxGB97MRhMSlbTwK1T5KAWOlqi5mJW5L6vNrQ
7Tra/YceH70fU0fJYOXhBxM92NwD1bbVd9GPYFSqrdrVj19bvo63XsxZduex5QHr
RkWqT5w5mgAHaEgCqWrS/64q9TR9UEwrB8kiZZg3k9/im+zBwEULTZu0r8oMEkpj
bTlXLmt8EMBqxwIDAQABo1AwTjAdBgNVHQ4EFgQUcH8uroNoWZgEIyrN6z4XzSTd
AUkwHwYDVR0jBBgwFoAUcH8uroNoWZgEIyrN6z4XzSTdAUkwDAYDVR0TBAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAQEAuiLq2lhcOJHrwUP0txbHk2vy6rmGTPxqmcCo
CUQFZ3KrvUQM+rtRqqQ0+LzU4wSTFogBz9KSMfT03gPegY3b/7L2TOaMmUFRzTdd
c9PNT0lP8V3pNQrxp0IjKir791QkGe2Ux45iMKf/SXpeTWASp4zeMiD6/LXFzzaK
BfNS5IrIWRDev41lFasDzudK5/kmVaMvDOFyW51KkKkqb64VS4UA81JIEzClvz+3
Vp3k1AXup5+XnTvhqu2nRhrLpJR5w8OXQpcn6qjKlVc2BXtb3xwci1/ibHlZy3CZ
n70e2NYihU5yYKccReP+fjLgVFsuhsDs/0hRML1u9bLp9nUbYA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC/mhXWzc26ztIg
2Duia7kDG54SAr3uaHk9TeGBmmWJIVoRKYvaosZ4/rT2hez/rxcNdVbi61QsI6Mu
HSen7lfLeLcZENeAFnvZAN7bdaqpCqpoGVBVWbVbEb5qZG1kkRZ1IiyIUG2T7x0E
SUeHZZAOEM5aocYdBqtCAk/EYH3sxGExKVtPArVPkoBY6WqLmYlbkvq82tDtOtr9
hx4fvR9TR8lg5eEHEz3Y3APVttV30Y9gVKqt2tWPX1u+jrdezFl257HlAetGRapP
nDmaAAdoSAKpatL/rir1NH1QTCsHySJlmDeT3+Kb7MHARQtNm7SvygwSSmNtOVcu
a3wQwGrHAgMBAAECggEBAL4rWle8JuCuHGNbGz1nO9d41tg7fnYdnZAaN6OiMfr8
bl+wY84aV3GKJOS2InfYOcIy340UU5QHvxOq/kwwRVV/uAOZ8rqAFmZY9djOnhdv
rZjq3xAHnPgJ0XvZt7XkR2z1AUw+v7Pf1WYGsYcSZ/t99MKB5Je0odA/aRqZRwLy
YflbsnAJtxdJ6fsiVCSJcU76V8sxfiCimw6ppLMEp3zCjveQ5Lv0eVoL2zNYeh+l
GiSwqTqaR+WJekkDiXRd9KYI19drf7OkTII1DtOd6bgvKX3zv2lNiere4J4k7cAP
rW6fBFgtSq2oklTpWUlXRH7XQAgDtDvldXdlKaj96dkCgYEA8KPSu5ywg8pjCofE
nLtJTfVyD2g9tgNLj9dI3kuSniZU51kOtk5rZZwL0S8piGczL908aV9DIWdXWsND
5hlXquKUTSjxPYEzZvaN+tvf9e0AcY/D/UaK0mKPjEbh7vg6pS77aZZz2EL2inOs
dam8famOOC9RUkxH5JWa3UV4UhsCgYEAy9T0wPQctjuvDkZQTqKEKsHrmrgY2PXT
Re8DDGI8hxjYb8l+NoFQ7eiwTHir/DULupxQoBBUQtS+idQzUu02tzLMnGcjHNwh
Tu+vZ4xlVnXxfgIRjDKkfQjiAC5SLzoNO9Jn8g4eS/1mEPXhQ0TXIsFonZDypp/n
RMp21DkvdMUCgYAIMgwjR5rbYjEtUqJnlBlTBmD0FWDEqigQpgxdRcWgjT2nA2l0
3AbcVwwv+6M2eg1MPASqsgvfP13CQZQ2afaKY10Zo6NTrOrLPupm+MYP4hp5w6Ox
JI3lzGWHKYLYWKvmpEr7tZwMaXtsC7R77WP2A6hMUZA7dU2dg1ra3lrSsQKBgQDA
sPIsUtmtwOBtqzUSEXrGfQqA+larDEGNVDVaiKfVwzwg+aeyWS+rqRS5Rj64L2GG
KW3i020EvN/fplZap9vY9lIN7UZ5avSmDdqRFl1ajiccy1HRarKrbTFRoHibItMN
4YvYfVZQ2h2aHQe2Myb6OULv6e4qbPIRyyDo4aKmTQKBgQCadq2JfICFIP9Q1aQn
93oD7Z4WcYs+KsLYO+/uJxWMrn0/gv90cGrSfstJqDOHnRq4WKUcgK9ErxaE4LkW
sD0mBhRM3SMxnRJZRO+6roRdehtjHkvzKu75KjcsuwefoMs2sFa4CLQ1YU2vO3Tx
dgzpnKS2bH/i5yLwhelRfddZ6Q==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdSb290
IENBMCAXDTIzMTAzMDEwMjYxNloYDzIxMjMxMDMxMTAyNjE2WjAUMRIwEAYDVQQD
DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCk6ujS
x/spB5QEiXy4gNe2ETgXFfWxk4WldQRb+pk6QBNMMLaIRG+bpN7bHnXxMKj5hmoj
gPYUYsUquWkv5RjDCRRty2uV/If8fGWfJnyiRWaiLcXu0GqxvQpISOOnSmAvwJEx
zl5rz8ESATYxGfedqJPXUHNa4CrMpAY5ugsisA0KuaD0xrRD2dQ8Ub8pbibEKey+
M0/uVMSgMbyEthRmRTkv4UufHqwxeKk0LlGi6IeZa+rqCkBObkcFiErc7ms+1IKO
cJJ6ib2uiZt+1we8zIaob/iPekAjCakghY1Ba7ZBLpPxkM2tTfxPnE1KoiuludOq
4tZCoULHl1iJuIYHAgMBAAGjYjBgMB0GA1UdDgQWBBQtMXuC2ST9usgeZ0mpVcdJ
CxRPnjAfBgNVHSMEGDAWgBRwfy6ug2hZmAQjKs3rPhfNJN0BSTAJBgNVHRMEAjAA
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQCqXUb/TGdB
ARHt/MysFv4Tx3dOpdqR+buSvIfK3eRO3lmZdIVsPGWODZvpW2hAgkHSIevkhMi4
VI97G8fk4SNDfg+O+rTA8/OlP1GBtbKXnAKdii5Y3RciQOtzp54BzM9rx2YhCzTu
vESEPzk3fAtAgKWFCAkj1Oh7fHykwNC7Xj0WgYcNlrIJKb6EQ76AgA0MHntnYZbY
Hr4D/TxjoGxhEisjPdYfagQhTtTeYDQiEDTr79Lnclj5EPLQ3Da8c7DG8TIjCVWf
KPyTW3uKTqCiGRkJPD+sCHSy9OvJFUf9XLpkaYL5UUpsKzswLZFjER+3VeARtbpN
VTr7JU5bxYhK
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCk6ujSx/spB5QE
iXy4gNe2ETgXFfWxk4WldQRb+pk6QBNMMLaIRG+bpN7bHnXxMKj5hmojgPYUYsUq
uWkv5RjDCRRty2uV/If8fGWfJnyiRWaiLcXu0GqxvQpISOOnSmAvwJExzl5rz8ES
ATYxGfedqJPXUHNa4CrMpAY5ugsisA0KuaD0xrRD2dQ8Ub8pbibEKey+M0/uVMSg
MbyEthRmRTkv4UufHqwxeKk0LlGi6IeZa+rqCkBObkcFiErc7ms+1IKOcJJ6ib2u
iZt+1we8zIaob/iPekAjCakghY1Ba7ZBLpPxkM2tTfxPnE1KoiuludOq4tZCoULH
l1iJuIYHAgMBAAECggEACZE/NIs5fOXdpm27eJCw8vUIxf4WJNkkFbc2K4fcP87b
z727uSgPOX5VF20q9nUWOHOd0LV4kTIxsgrTmV23FAmAz+XPNgJSeUlWM+dtr5RL
Ifl51CLvLaSD5jGkU14zOlH3mmYYgDSrRLohRLP284SGHyWhq5H5qamSWuL6Jmbs
YWwgbHdHQvo+Rl7PVg2aUWdTHr+tb1S/SH+iePze2dyZrQ0fCkzK3leoMwaJvUM/
v/FaDYxsZYzSQZJPOVpdzHPkwm4ywaCgztQ5Qyy6Lr7bqyK6M8EzGWoOQtMaqHCg
0t7AWh+VXxl3BIwSjAHgb/5OpAuYfVCT2p38wMhhYQKBgQDTB9r7tFhytxC/yDXT
A0xGnrPR6oTTmZNiQee4ZxlyI9DLa59l16piZInv9nx9sGkRofHm7EUBN/br6G46
+I8TauE3KM2qWk/U+mAJklydVRi5U6+bY3871l6eJE+otxOYa4jKGQ2YTTsFjAWr
22knbTR130OQU25GpSu3easDDwKBgQDID36BHw24Cexpp+HmtEa/wjyRMX10c9na
IxvlGcAyTYjLYghBHyIQOMO6iqyGQidSMzGzRAi3wBA2/yr59tloVjFttwt2WEnn
qblAoEIIrE/aH++KqAxUydRoP9sHLiVlpTJMJLzhKb9UFjMsZ4SrNx/JGbZmU9uC
C/EgIrHtiQKBgB3XB4T9/F/EOQ8VTV8YIUn/GOg+5CdTmP6U2SI/Gd8E53pMLo7l
Dwe4tbSDwxi2wDSpFJ6VnDBO7JBxHl0iVoDlZRE6qNJE0PMJsFjKJGRu6v8RsUwk
ppIcfuaXtdfig1fTJNWG82As04K2SPsDHHxhucBNIK2gzoAYzPS1tJPLAoGBAMBl
NjGS3aypznPlgfhOUuPDNmAjihTd/RotPXxcAVve+LkvM+T8vdN/46uYBUawhAQn
O5q8yO19hZp+VqRBYt9WVP7AVAOh8KEbtg6SkC6rF7gbklB0QDeiSeVf05HaLRjN
f8t+YS7g6SFCoEAJ5aqKvsS1N5a8+pLcTS2scBSRAoGBAKW0Aq5SdKR3RJ6TWFUQ
J02A68ri95EmCKPx14gXwyyWzT/a8mzv4V/BUdTGZY8lPQYL87U0rXrdFbI2lP67
CmZI7qokmFkRNjQW7semwNZixW+R1N7cudhbdEjrho+yY/MK2UDIUD/RdPLYz33y
h/LhOZwTOJijh/Q96qW3OtAX
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,296 @@
/*
* Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-tls-client-block.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_STREAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Helper function to create a BIO connected to the server */
static BIO *create_socket_bio(const char *hostname, const char *port, int family)
{
int sock = -1;
BIO_ADDRINFO *res;
const BIO_ADDRINFO *ai = NULL;
BIO *bio;
/*
* Lookup IP address info for the server.
*/
if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 0,
&res))
return NULL;
/*
* Loop through all the possible addresses for the server and find one
* we can connect to.
*/
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/*
* Create a TCP socket. We could equally use non-OpenSSL calls such
* as "socket" here for this and the subsequent connect and close
* functions. But for portability reasons and also so that we get
* errors on the OpenSSL stack in the event of a failure we use
* OpenSSL's versions of these functions.
*/
sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_STREAM, 0, 0);
if (sock == -1)
continue;
/* Connect the socket to the server's address */
if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), BIO_SOCK_NODELAY)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
/* We have a connected socket so break out of the loop */
break;
}
/* Free the address information resources we allocated earlier */
BIO_ADDRINFO_free(res);
/* If sock is -1 then we've been unable to connect to the server */
if (sock == -1)
return NULL;
/* Create a BIO to wrap the socket */
bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
BIO_closesocket(sock);
return NULL;
}
/*
* Associate the newly created BIO with the underlying socket. By
* passing BIO_CLOSE here the socket will be automatically closed when
* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
* case you must close the socket explicitly when it is no longer
* needed.
*/
BIO_set_fd(bio, sock, BIO_CLOSE);
return bio;
}
/*
* Simple application to send a basic HTTP/1.0 request to a server and
* print the response on the screen.
*/
int main(int argc, char *argv[])
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
BIO *bio = NULL;
int res = EXIT_FAILURE;
int ret;
const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
const char *request_end = "\r\n\r\n";
size_t written, readbytes;
char buf[160];
char *hostname, *port;
int argnext = 1;
int ipv6 = 0;
if (argc < 3) {
printf("Usage: tls-client-block [-6] hostname port\n");
goto end;
}
if (!strcmp(argv[argnext], "-6")) {
if (argc < 4) {
printf("Usage: tls-client-block [-6] hostname port\n");
goto end;
}
ipv6 = 1;
argnext++;
}
hostname = argv[argnext++];
port = argv[argnext];
/*
* Create an SSL_CTX which we can use to create SSL objects from. We
* want an SSL_CTX for creating clients so we use TLS_client_method()
* here.
*/
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
printf("Failed to create the SSL_CTX\n");
goto end;
}
/*
* Configure the client to abort the handshake if certificate
* verification fails. Virtually all clients should do this unless you
* really know what you are doing.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Use the default trusted certificate store */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
printf("Failed to set the default trusted certificate store\n");
goto end;
}
/*
* TLSv1.1 or earlier are deprecated by IETF and are generally to be
* avoided if possible. We require a minimum TLS version of TLSv1.2.
*/
if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
printf("Failed to set the minimum TLS protocol version\n");
goto end;
}
/* Create an SSL object to represent the TLS connection */
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create the SSL object\n");
goto end;
}
/*
* Create the underlying transport socket/BIO and associate it with the
* connection.
*/
bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET);
if (bio == NULL) {
printf("Failed to create the BIO\n");
goto end;
}
SSL_set_bio(ssl, bio, bio);
/*
* Tell the server during the handshake which hostname we are attempting
* to connect to in case the server supports multiple hosts.
*/
if (!SSL_set_tlsext_host_name(ssl, hostname)) {
printf("Failed to set the SNI hostname\n");
goto end;
}
/*
* Ensure we check during certificate verification that the server has
* supplied a certificate for the hostname that we were expecting.
* Virtually all clients should do this unless you really know what you
* are doing.
*/
if (!SSL_set1_host(ssl, hostname)) {
printf("Failed to set the certificate verification hostname");
goto end;
}
/* Do the handshake with the server */
if (SSL_connect(ssl) < 1) {
printf("Failed to connect to the server\n");
/*
* If the failure is due to a verification error we can get more
* information about it from SSL_get_verify_result().
*/
if (SSL_get_verify_result(ssl) != X509_V_OK)
printf("Verify error: %s\n",
X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
goto end;
}
/* Write an HTTP GET request to the peer */
if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
printf("Failed to write start of HTTP request\n");
goto end;
}
if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
printf("Failed to write hostname in HTTP request\n");
goto end;
}
if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
printf("Failed to write end of HTTP request\n");
goto end;
}
/*
* Get up to sizeof(buf) bytes of the response. We keep reading until the
* server closes the connection.
*/
while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
/*
* OpenSSL does not guarantee that the returned data is a string or
* that it is NUL terminated so we use fwrite() to write the exact
* number of bytes that we read. The data could be non-printable or
* have NUL characters in the middle of it. For this simple example
* we're going to print it to stdout anyway.
*/
fwrite(buf, 1, readbytes, stdout);
}
/* In case the response didn't finish with a newline we add one now */
printf("\n");
/*
* Check whether we finished the while loop above normally or as the
* result of an error. The 0 argument to SSL_get_error() is the return
* code we received from the SSL_read_ex() call. It must be 0 in order
* to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN.
*/
if (SSL_get_error(ssl, 0) != SSL_ERROR_ZERO_RETURN) {
/*
* Some error occurred other than a graceful close down by the
* peer.
*/
printf ("Failed reading remaining data\n");
goto end;
}
/*
* The peer already shutdown gracefully (we know this because of the
* SSL_ERROR_ZERO_RETURN above). We should do the same back.
*/
ret = SSL_shutdown(ssl);
if (ret < 1) {
/*
* ret < 0 indicates an error. ret == 0 would be unexpected here
* because that means "we've sent a close_notify and we're waiting
* for one back". But we already know we got one from the peer
* because of the SSL_ERROR_ZERO_RETURN above.
*/
printf("Error shutting down\n");
goto end;
}
/* Success! */
res = EXIT_SUCCESS;
end:
/*
* If something bad happened then we will dump the contents of the
* OpenSSL error stack to stderr. There might be some useful diagnostic
* information there.
*/
if (res == EXIT_FAILURE)
ERR_print_errors_fp(stderr);
/*
* Free the resources we allocated. We do not free the BIO object here
* because ownership of it was immediately transferred to the SSL object
* via SSL_set_bio(). The BIO will be freed when we free the SSL object.
*/
SSL_free(ssl);
SSL_CTX_free(ctx);
return res;
}

View File

@@ -0,0 +1,376 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-tls-client-non-block.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_STREAM */
#ifdef _WIN32 /* Windows */
# include <winsock2.h>
#else /* Linux/Unix */
# include <sys/socket.h>
# include <sys/select.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
/* Helper function to create a BIO connected to the server */
static BIO *create_socket_bio(const char *hostname, const char *port, int family)
{
int sock = -1;
BIO_ADDRINFO *res;
const BIO_ADDRINFO *ai = NULL;
BIO *bio;
/*
* Lookup IP address info for the server.
*/
if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 0,
&res))
return NULL;
/*
* Loop through all the possible addresses for the server and find one
* we can connect to.
*/
for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
/*
* Create a TCP socket. We could equally use non-OpenSSL calls such
* as "socket" here for this and the subsequent connect and close
* functions. But for portability reasons and also so that we get
* errors on the OpenSSL stack in the event of a failure we use
* OpenSSL's versions of these functions.
*/
sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_STREAM, 0, 0);
if (sock == -1)
continue;
/* Connect the socket to the server's address */
if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), BIO_SOCK_NODELAY)) {
BIO_closesocket(sock);
sock = -1;
continue;
}
/* Set to nonblocking mode */
if (!BIO_socket_nbio(sock, 1)) {
sock = -1;
continue;
}
/* We have a connected socket so break out of the loop */
break;
}
/* Free the address information resources we allocated earlier */
BIO_ADDRINFO_free(res);
/* If sock is -1 then we've been unable to connect to the server */
if (sock == -1)
return NULL;
/* Create a BIO to wrap the socket */
bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
BIO_closesocket(sock);
return NULL;
}
/*
* Associate the newly created BIO with the underlying socket. By
* passing BIO_CLOSE here the socket will be automatically closed when
* the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
* case you must close the socket explicitly when it is no longer
* needed.
*/
BIO_set_fd(bio, sock, BIO_CLOSE);
return bio;
}
static void wait_for_activity(SSL *ssl, int write)
{
fd_set fds;
int width, sock;
/* Get hold of the underlying file descriptor for the socket */
sock = SSL_get_fd(ssl);
FD_ZERO(&fds);
FD_SET(sock, &fds);
width = sock + 1;
/*
* Wait until the socket is writeable or readable. We use select here
* for the sake of simplicity and portability, but you could equally use
* poll/epoll or similar functions
*
* NOTE: For the purposes of this demonstration code this effectively
* makes this demo block until it has something more useful to do. In a
* real application you probably want to go and do other work here (e.g.
* update a GUI, or service other connections).
*
* Let's say for example that you want to update the progress counter on
* a GUI every 100ms. One way to do that would be to add a 100ms timeout
* in the last parameter to "select" below. Then, when select returns,
* you check if it did so because of activity on the file descriptors or
* because of the timeout. If it is due to the timeout then update the
* GUI and then restart the "select".
*/
if (write)
select(width, NULL, &fds, NULL, NULL);
else
select(width, &fds, NULL, NULL, NULL);
}
static int handle_io_failure(SSL *ssl, int res)
{
switch (SSL_get_error(ssl, res)) {
case SSL_ERROR_WANT_READ:
/* Temporary failure. Wait until we can read and try again */
wait_for_activity(ssl, 0);
return 1;
case SSL_ERROR_WANT_WRITE:
/* Temporary failure. Wait until we can write and try again */
wait_for_activity(ssl, 1);
return 1;
case SSL_ERROR_ZERO_RETURN:
/* EOF */
return 0;
case SSL_ERROR_SYSCALL:
return -1;
case SSL_ERROR_SSL:
/*
* If the failure is due to a verification error we can get more
* information about it from SSL_get_verify_result().
*/
if (SSL_get_verify_result(ssl) != X509_V_OK)
printf("Verify error: %s\n",
X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
return -1;
default:
return -1;
}
}
/*
* Simple application to send a basic HTTP/1.0 request to a server and
* print the response on the screen.
*/
int main(int argc, char *argv[])
{
SSL_CTX *ctx = NULL;
SSL *ssl = NULL;
BIO *bio = NULL;
int res = EXIT_FAILURE;
int ret;
const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
const char *request_end = "\r\n\r\n";
size_t written, readbytes = 0;
char buf[160];
int eof = 0;
char *hostname, *port;
int argnext = 1;
int ipv6 = 0;
if (argc < 3) {
printf("Usage: tls-client-non-block [-6] hostname port\n");
goto end;
}
if (!strcmp(argv[argnext], "-6")) {
if (argc < 4) {
printf("Usage: tls-client-non-block [-6] hostname port\n");
goto end;
}
ipv6 = 1;
argnext++;
}
hostname = argv[argnext++];
port = argv[argnext];
/*
* Create an SSL_CTX which we can use to create SSL objects from. We
* want an SSL_CTX for creating clients so we use TLS_client_method()
* here.
*/
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
printf("Failed to create the SSL_CTX\n");
goto end;
}
/*
* Configure the client to abort the handshake if certificate
* verification fails. Virtually all clients should do this unless you
* really know what you are doing.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
/* Use the default trusted certificate store */
if (!SSL_CTX_set_default_verify_paths(ctx)) {
printf("Failed to set the default trusted certificate store\n");
goto end;
}
/*
* TLSv1.1 or earlier are deprecated by IETF and are generally to be
* avoided if possible. We require a minimum TLS version of TLSv1.2.
*/
if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
printf("Failed to set the minimum TLS protocol version\n");
goto end;
}
/* Create an SSL object to represent the TLS connection */
ssl = SSL_new(ctx);
if (ssl == NULL) {
printf("Failed to create the SSL object\n");
goto end;
}
/*
* Create the underlying transport socket/BIO and associate it with the
* connection.
*/
bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET);
if (bio == NULL) {
printf("Failed to crete the BIO\n");
goto end;
}
SSL_set_bio(ssl, bio, bio);
/*
* Tell the server during the handshake which hostname we are attempting
* to connect to in case the server supports multiple hosts.
*/
if (!SSL_set_tlsext_host_name(ssl, hostname)) {
printf("Failed to set the SNI hostname\n");
goto end;
}
/*
* Ensure we check during certificate verification that the server has
* supplied a certificate for the hostname that we were expecting.
* Virtually all clients should do this unless you really know what you
* are doing.
*/
if (!SSL_set1_host(ssl, hostname)) {
printf("Failed to set the certificate verification hostname");
goto end;
}
/* Do the handshake with the server */
while ((ret = SSL_connect(ssl)) != 1) {
if (handle_io_failure(ssl, ret) == 1)
continue; /* Retry */
printf("Failed to connect to server\n");
goto end; /* Cannot retry: error */
}
/* Write an HTTP GET request to the peer */
while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write start of HTTP request\n");
goto end; /* Cannot retry: error */
}
while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write hostname in HTTP request\n");
goto end; /* Cannot retry: error */
}
while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
if (handle_io_failure(ssl, 0) == 1)
continue; /* Retry */
printf("Failed to write end of HTTP request\n");
goto end; /* Cannot retry: error */
}
do {
/*
* Get up to sizeof(buf) bytes of the response. We keep reading until
* the server closes the connection.
*/
while (!eof && !SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
switch (handle_io_failure(ssl, 0)) {
case 1:
continue; /* Retry */
case 0:
eof = 1;
continue;
case -1:
default:
printf("Failed reading remaining data\n");
goto end; /* Cannot retry: error */
}
}
/*
* OpenSSL does not guarantee that the returned data is a string or
* that it is NUL terminated so we use fwrite() to write the exact
* number of bytes that we read. The data could be non-printable or
* have NUL characters in the middle of it. For this simple example
* we're going to print it to stdout anyway.
*/
if (!eof)
fwrite(buf, 1, readbytes, stdout);
} while (!eof);
/* In case the response didn't finish with a newline we add one now */
printf("\n");
/*
* The peer already shutdown gracefully (we know this because of the
* SSL_ERROR_ZERO_RETURN (i.e. EOF) above). We should do the same back.
*/
while ((ret = SSL_shutdown(ssl)) != 1) {
if (ret < 0 && handle_io_failure(ssl, ret) == 1)
continue; /* Retry */
/*
* ret == 0 is unexpected here because that means "we've sent a
* close_notify and we're waiting for one back". But we already know
* we got one from the peer because of the SSL_ERROR_ZERO_RETURN
* (i.e. EOF) above.
*/
printf("Error shutting down\n");
goto end; /* Cannot retry: error */
}
/* Success! */
res = EXIT_SUCCESS;
end:
/*
* If something bad happened then we will dump the contents of the
* OpenSSL error stack to stderr. There might be some useful diagnostic
* information there.
*/
if (res == EXIT_FAILURE)
ERR_print_errors_fp(stderr);
/*
* Free the resources we allocated. We do not free the BIO object here
* because ownership of it was immediately transferred to the SSL object
* via SSL_set_bio(). The BIO will be freed when we free the SSL object.
*/
SSL_free(ssl);
SSL_CTX_free(ctx);
return res;
}

View File

@@ -0,0 +1,284 @@
/*
* Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: Changes to this file should also be reflected in
* doc/man7/ossl-guide-tls-server-block.pod
*/
#include <string.h>
/* Include the appropriate header file for SOCK_STREAM */
#ifdef _WIN32 /* Windows */
# include <stdarg.h>
# include <winsock2.h>
#else /* Linux/Unix */
# include <err.h>
# include <sys/socket.h>
# include <sys/select.h>
#endif
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
static const char cache_id[] = "OpenSSL Demo Server";
#ifdef _WIN32
static const char *progname;
static void vwarnx(const char *fmt, va_list ap)
{
if (progname != NULL)
fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
putc('\n', stderr);
}
static void errx(int status, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
exit(status);
}
static void warnx(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vwarnx(fmt, ap);
va_end(ap);
}
#endif
/* Minimal TLS echo server. */
int main(int argc, char *argv[])
{
int res = EXIT_FAILURE;
long opts;
const char *hostport;
SSL_CTX *ctx = NULL;
BIO *acceptor_bio;
#ifdef _WIN32
progname = argv[0];
#endif
if (argc != 2)
errx(res, "Usage: %s [host:]port", argv[0]);
hostport = argv[1];
/*
* An SSL_CTX holds shared configuration information for multiple
* subsequent per-client SSL connections.
*/
ctx = SSL_CTX_new(TLS_server_method());
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
errx(res, "Failed to create server SSL_CTX");
}
/*
* TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD
* be avoided if possible.
*/
if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
SSL_CTX_free(ctx);
ERR_print_errors_fp(stderr);
errx(res, "Failed to set the minimum TLS protocol version");
}
#if 0
/*
* In applications (e.g. SMTP) where most clients are performing
* unauthenticated opportunistic TLS it may make sense to set the security
* level to 0, allowing weaker encryption parameters, which are still
* stronger than a potential cleartext fallback.
*
* The default security level is 2 (as of OpenSSL 3.2), which is roughly
* equivalent to that of 112 bit symmetric keys, or 2048-bit RSA or
* finite-field Diffie-Hellman keys. Notably, non-zero security levels no
* longer allow the use of SHA-1 in certificate signatures, key exchange
* or in the TLS 1.[01] PRF (so TLS 1.0 and 1.1 require security level 0).
*/
SSL_CTX_set_security_level(ctx, 0);
#endif
/*
* Tolerate clients hanging up without a TLS "shutdown". Appropriate in all
* application protocols which perform their own message "framing", and
* don't rely on TLS to defend against "truncation" attacks.
*/
opts = SSL_OP_IGNORE_UNEXPECTED_EOF;
/*
* Block potential CPU-exhaustion attacks by clients that request frequent
* renegotiation. This is of course only effective if there are existing
* limits on initial full TLS handshake or connection rates.
*/
opts |= SSL_OP_NO_RENEGOTIATION;
/*
* Most servers elect to use their own cipher preference rather than that of
* the client.
*/
opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
/* Apply the selection options */
SSL_CTX_set_options(ctx, opts);
/*
* Load the server's certificate *chain* file (PEM format), which includes
* not only the leaf (end-entity) server certificate, but also any
* intermediate issuer-CA certificates. The leaf certificate must be the
* first certificate in the file.
*
* In advanced use-cases this can be called multiple times, once per public
* key algorithm for which the server has a corresponding certificate.
* However, the corresponding private key (see below) must be loaded first,
* *before* moving on to the next chain file.
*
* The requisite files "chain.pem" and "pkey.pem" can be generated by running
* "make chain" in this directory. If the server will be executed from some
* other directory, move or copy the files there.
*/
if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) {
SSL_CTX_free(ctx);
ERR_print_errors_fp(stderr);
errx(res, "Failed to load the server certificate chain file");
}
/*
* Load the corresponding private key, this also checks that the private
* key matches the just loaded end-entity certificate. It does not check
* whether the certificate chain is valid, the certificates could be
* expired, or may otherwise fail to form a chain that a client can validate.
*/
if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) {
SSL_CTX_free(ctx);
ERR_print_errors_fp(stderr);
errx(res, "Error loading the server private key file, "
"possible key/cert mismatch???");
}
/*
* Servers that want to enable session resumption must specify a cache id
* byte array, that identifies the server application, and reduces the
* chance of inappropriate cache sharing.
*/
SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id));
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
/*
* How many client TLS sessions to cache. The default is
* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions),
* which may be too small or too large.
*/
SSL_CTX_sess_set_cache_size(ctx, 1024);
/*
* Sessions older than this are considered a cache miss even if still in
* the cache. The default is two hours. Busy servers whose clients make
* many connections in a short burst may want a shorter timeout, on lightly
* loaded servers with sporadic connections from any given client, a longer
* time may be appropriate.
*/
SSL_CTX_set_timeout(ctx, 3600);
/*
* Clients rarely employ certificate-based authentication, and so we don't
* require "mutual" TLS authentication (indeed there's no way to know
* whether or how the client authenticated the server, so the term "mutual"
* is potentially misleading).
*
* Since we're not soliciting or processing client certificates, we don't
* need to configure a trusted-certificate store, so no call to
* SSL_CTX_set_default_verify_paths() is needed. The server's own
* certificate chain is assumed valid.
*/
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
/*
* Create a listener socket wrapped in a BIO.
* The first call to BIO_do_accept() initialises the socket
*/
acceptor_bio = BIO_new_accept(hostport);
if (acceptor_bio == NULL) {
SSL_CTX_free(ctx);
ERR_print_errors_fp(stderr);
errx(res, "Error creating acceptor bio");
}
BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR);
if (BIO_do_accept(acceptor_bio) <= 0) {
SSL_CTX_free(ctx);
ERR_print_errors_fp(stderr);
errx(res, "Error setting up acceptor socket");
}
/* Wait for incoming connection */
for (;;) {
BIO *client_bio;
SSL *ssl;
unsigned char buf[8192];
size_t nread;
size_t nwritten;
size_t total = 0;
/* Pristine error stack for each new connection */
ERR_clear_error();
/* Wait for the next client to connect */
if (BIO_do_accept(acceptor_bio) <= 0) {
/* Client went away before we accepted the connection */
continue;
}
/* Pop the client connection from the BIO chain */
client_bio = BIO_pop(acceptor_bio);
fprintf(stderr, "New client connection accepted\n");
/* Associate a new SSL handle with the new connection */
if ((ssl = SSL_new(ctx)) == NULL) {
ERR_print_errors_fp(stderr);
warnx("Error creating SSL handle for new connection");
BIO_free(client_bio);
continue;
}
SSL_set_bio(ssl, client_bio, client_bio);
/* Attempt an SSL handshake with the client */
if (SSL_accept(ssl) <= 0) {
ERR_print_errors_fp(stderr);
warnx("Error performing SSL handshake with client");
SSL_free(ssl);
continue;
}
while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) {
if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 &&
nwritten == nread) {
total += nwritten;
continue;
}
warnx("Error echoing client input");
break;
}
fprintf(stderr, "Client connection closed, %zu bytes sent\n", total);
SSL_free(ssl);
}
/*
* Unreachable placeholder cleanup code, the above loop runs forever.
*/
SSL_CTX_free(ctx);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,22 @@
#
# To run the demo when linked with a shared library (default) ensure that
# libcrypto and libssl are on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./ossl-nghttp3-demo www.example.com:443
CFLAGS += -I../../include -g -Wall -Wsign-compare
LDFLAGS += -L../..
LDLIBS = -lcrypto -lssl -lnghttp3
all: ossl-nghttp3-demo
ossl-nghttp3-demo: ossl-nghttp3-demo.o ossl-nghttp3.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
clean:
$(RM) ossl-nghttp3-demo *.o
.PHONY: test
test: all
@echo "\nHTTP/3 tests:"
@echo "skipped"

View File

@@ -0,0 +1,39 @@
HTTP/3 Demo using OpenSSL QUIC and nghttp3
==========================================
This is a simple demo of how to use HTTP/3 with OpenSSL QUIC using the HTTP/3
library “[nghttp3](https://github.com/ngtcp2/nghttp3)”.
The demo is structured into two parts:
- an adaptation layer which binds nghttp3 to OpenSSL's QUIC implementation
(`ossl-nghttp3.c`);
- a simple application which makes an HTTP/3 request using this adaptation
layer (`ossl-nghttp3-demo.c`).
The Makefile in this directory can be used to build the demo on \*nix-style
systems. You will need the `nghttp3` library and header file. On
Ubuntu, these can be obtained by installing the package `libnghttp3-dev`.
Running the Demo
----------------
Depending on your system configuration it may be necessary to set the
`SSL_CERT_FILE` or `SSL_CERT_DIR` environment variables to a location where
trusted root CA certificates can be found.
After building by running `make`, run `./ossl-nghttp3-demo` with a hostname and
port as the sole argument:
```shell
$ make
$ LD_LIBRARY_PATH=../.. ./ossl-nghttp3-demo www.google.com:443
```
The demo produces the HTTP response headers in textual form as output followed
by the response body.
See Also
--------
- [nghttp3](https://github.com/ngtcp2/nghttp3)

View File

@@ -0,0 +1,16 @@
#
# To run the demo when linked with a shared library (default) ensure that
# libcrypto and libssl are on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./ossl-nghttp3-demo www.example.com:443
PROGRAMS{noinst} = ossl-nghttp3-demo
GENERATE[libnghttp3.so libnghttp3.a libnghttp3.dylib libnghttp3.lib libnghttp3.dll]=gen_nghttp3.pl
DEPEND[ossl-nghttp3-demo.o]=libnghttp3.so libnghttp3.a libnghttp3.dylib libnghttp3.lib libnghttp3.dll
DEPEND[ossl-nghttp3.o]=libnghttp3.so libnghttp3.a libnghttp3.dylib libnghttp3.lib libnghttp3.dll
INCLUDE[ossl-nghttp3-demo]=../../include nghttp3/lib/includes nghttp3/build/lib/includes
INCLUDE[ossl-nghttp3]=../../include nghttp3/lib/includes nghttp3/build/lib/includes
SOURCE[ossl-nghttp3-demo]=ossl-nghttp3.c ossl-nghttp3-demo.c
DEPEND[ossl-nghttp3-demo]=../../libcrypto ../../libssl ./libnghttp3

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env perl
#
use File::Copy;
use File::Path;
use Fcntl ':flock';
use strict;
use warnings;
#open STDOUT, '>&STDERR';
chdir "demos/http3";
open(my $fh, '>>', './build.info') or die "Could not open build.info - $!";
flock($fh, LOCK_EX) or die "Could not lock build.info - $!";
if (-d "./nghttp3") {
rmtree("./nghttp3") or die "Cannot remove nghttp3: $!";
}
system("git clone https://github.com/ngtcp2/nghttp3.git");
chdir "nghttp3";
mkdir "build";
system("git submodule init ./lib/sfparse ./tests/munit");
system("git submodule update");
system("cmake -DENABLE_LIB_ONLY=1 -S . -B build");
system("cmake --build build");
my $libs="./build/lib/libnghttp*";
for my $file (glob $libs) {
copy($file, "..");
}
chdir "../../..";
close($fh);
exit(0);

View File

@@ -0,0 +1,150 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "ossl-nghttp3.h"
#include <openssl/err.h>
static int done;
static void make_nv(nghttp3_nv *nv, const char *name, const char *value)
{
nv->name = (uint8_t *)name;
nv->value = (uint8_t *)value;
nv->namelen = strlen(name);
nv->valuelen = strlen(value);
nv->flags = NGHTTP3_NV_FLAG_NONE;
}
static int on_recv_header(nghttp3_conn *h3conn, int64_t stream_id,
int32_t token,
nghttp3_rcbuf *name, nghttp3_rcbuf *value,
uint8_t flags,
void *conn_user_data,
void *stream_user_data)
{
nghttp3_vec vname, vvalue;
/* Received a single HTTP header. */
vname = nghttp3_rcbuf_get_buf(name);
vvalue = nghttp3_rcbuf_get_buf(value);
fwrite(vname.base, vname.len, 1, stderr);
fprintf(stderr, ": ");
fwrite(vvalue.base, vvalue.len, 1, stderr);
fprintf(stderr, "\n");
return 0;
}
static int on_end_headers(nghttp3_conn *h3conn, int64_t stream_id,
int fin,
void *conn_user_data, void *stream_user_data)
{
fprintf(stderr, "\n");
return 0;
}
static int on_recv_data(nghttp3_conn *h3conn, int64_t stream_id,
const uint8_t *data, size_t datalen,
void *conn_user_data, void *stream_user_data)
{
size_t wr;
/* HTTP response body data - write it to stdout. */
while (datalen > 0) {
wr = fwrite(data, 1, datalen, stdout);
if (ferror(stdout))
return 1;
data += wr;
datalen -= wr;
}
return 0;
}
static int on_end_stream(nghttp3_conn *h3conn, int64_t stream_id,
void *conn_user_data, void *stream_user_data)
{
/* HTTP transaction is done - set done flag so that we stop looping. */
done = 1;
return 0;
}
int main(int argc, char **argv)
{
int ret = 1;
SSL_CTX *ctx = NULL;
OSSL_DEMO_H3_CONN *conn = NULL;
nghttp3_nv nva[16];
nghttp3_callbacks callbacks = {0};
size_t num_nv = 0;
const char *addr;
/* Check arguments. */
if (argc < 2) {
fprintf(stderr, "usage: %s <host:port>\n", argv[0]);
goto err;
}
addr = argv[1];
/* Setup SSL_CTX. */
if ((ctx = SSL_CTX_new(OSSL_QUIC_client_method())) == NULL)
goto err;
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
if (SSL_CTX_set_default_verify_paths(ctx) == 0)
goto err;
/* Setup callbacks. */
callbacks.recv_header = on_recv_header;
callbacks.end_headers = on_end_headers;
callbacks.recv_data = on_recv_data;
callbacks.end_stream = on_end_stream;
/* Create connection. */
if ((conn = OSSL_DEMO_H3_CONN_new_for_addr(ctx, addr, &callbacks,
NULL, NULL)) == NULL) {
ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,
"cannot create HTTP/3 connection");
goto err;
}
/* Build HTTP headers. */
make_nv(&nva[num_nv++], ":method", "GET");
make_nv(&nva[num_nv++], ":scheme", "https");
make_nv(&nva[num_nv++], ":authority", addr);
make_nv(&nva[num_nv++], ":path", "/");
make_nv(&nva[num_nv++], "user-agent", "OpenSSL-Demo/nghttp3");
/* Submit request. */
if (!OSSL_DEMO_H3_CONN_submit_request(conn, nva, num_nv, NULL, NULL)) {
ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,
"cannot submit HTTP/3 request");
goto err;
}
/* Wait for request to complete. */
while (!done)
if (!OSSL_DEMO_H3_CONN_handle_events(conn)) {
ERR_raise_data(ERR_LIB_USER, ERR_R_OPERATION_FAIL,
"cannot handle events");
goto err;
}
ret = 0;
err:
if (ret != 0)
ERR_print_errors_fp(stderr);
OSSL_DEMO_H3_CONN_free(conn);
SSL_CTX_free(ctx);
return ret;
}

View File

@@ -0,0 +1,743 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "ossl-nghttp3.h"
#include <openssl/err.h>
#include <assert.h>
#define ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))
enum {
OSSL_DEMO_H3_STREAM_TYPE_CTRL_SEND,
OSSL_DEMO_H3_STREAM_TYPE_QPACK_ENC_SEND,
OSSL_DEMO_H3_STREAM_TYPE_QPACK_DEC_SEND,
OSSL_DEMO_H3_STREAM_TYPE_REQ,
};
#define BUF_SIZE 4096
struct ossl_demo_h3_stream_st {
uint64_t id; /* QUIC stream ID */
SSL *s; /* QUIC stream SSL object */
int done_recv_fin; /* Received FIN */
void *user_data;
uint8_t buf[BUF_SIZE];
size_t buf_cur, buf_total;
};
DEFINE_LHASH_OF_EX(OSSL_DEMO_H3_STREAM);
static void h3_stream_free(OSSL_DEMO_H3_STREAM *s)
{
if (s == NULL)
return;
SSL_free(s->s);
OPENSSL_free(s);
}
static unsigned long h3_stream_hash(const OSSL_DEMO_H3_STREAM *s)
{
return (unsigned long)s->id;
}
static int h3_stream_eq(const OSSL_DEMO_H3_STREAM *a, const OSSL_DEMO_H3_STREAM *b)
{
if (a->id < b->id) return -1;
if (a->id > b->id) return 1;
return 0;
}
void *OSSL_DEMO_H3_STREAM_get_user_data(const OSSL_DEMO_H3_STREAM *s)
{
return s->user_data;
}
struct ossl_demo_h3_conn_st {
/* QUIC connection SSL object */
SSL *qconn;
/* BIO wrapping QCSO */
BIO *qconn_bio;
/* HTTP/3 connection object */
nghttp3_conn *h3conn;
/* map of stream IDs to OSSL_DEMO_H3_STREAMs */
LHASH_OF(OSSL_DEMO_H3_STREAM) *streams;
/* opaque user data pointer */
void *user_data;
int pump_res;
size_t consumed_app_data;
/* Forwarding callbacks */
nghttp3_recv_data recv_data_cb;
nghttp3_stream_close stream_close_cb;
nghttp3_stop_sending stop_sending_cb;
nghttp3_reset_stream reset_stream_cb;
nghttp3_deferred_consume deferred_consume_cb;
};
void OSSL_DEMO_H3_CONN_free(OSSL_DEMO_H3_CONN *conn)
{
if (conn == NULL)
return;
lh_OSSL_DEMO_H3_STREAM_doall(conn->streams, h3_stream_free);
nghttp3_conn_del(conn->h3conn);
BIO_free_all(conn->qconn_bio);
lh_OSSL_DEMO_H3_STREAM_free(conn->streams);
OPENSSL_free(conn);
}
static OSSL_DEMO_H3_STREAM *h3_conn_create_stream(OSSL_DEMO_H3_CONN *conn, int type)
{
OSSL_DEMO_H3_STREAM *s;
uint64_t flags = SSL_STREAM_FLAG_ADVANCE;
if ((s = OPENSSL_zalloc(sizeof(OSSL_DEMO_H3_STREAM))) == NULL)
return NULL;
if (type != OSSL_DEMO_H3_STREAM_TYPE_REQ)
flags |= SSL_STREAM_FLAG_UNI;
if ((s->s = SSL_new_stream(conn->qconn, flags)) == NULL) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"could not create QUIC stream object");
goto err;
}
s->id = SSL_get_stream_id(s->s);
lh_OSSL_DEMO_H3_STREAM_insert(conn->streams, s);
return s;
err:
OPENSSL_free(s);
return NULL;
}
static OSSL_DEMO_H3_STREAM *h3_conn_accept_stream(OSSL_DEMO_H3_CONN *conn, SSL *qstream)
{
OSSL_DEMO_H3_STREAM *s;
if ((s = OPENSSL_zalloc(sizeof(OSSL_DEMO_H3_STREAM))) == NULL)
return NULL;
s->id = SSL_get_stream_id(qstream);
s->s = qstream;
lh_OSSL_DEMO_H3_STREAM_insert(conn->streams, s);
return s;
}
static void h3_conn_remove_stream(OSSL_DEMO_H3_CONN *conn, OSSL_DEMO_H3_STREAM *s)
{
if (s == NULL)
return;
lh_OSSL_DEMO_H3_STREAM_delete(conn->streams, s);
h3_stream_free(s);
}
static int h3_conn_recv_data(nghttp3_conn *h3conn, int64_t stream_id,
const uint8_t *data, size_t datalen,
void *conn_user_data, void *stream_user_data)
{
OSSL_DEMO_H3_CONN *conn = conn_user_data;
conn->consumed_app_data += datalen;
if (conn->recv_data_cb == NULL)
return 0;
return conn->recv_data_cb(h3conn, stream_id, data, datalen,
conn_user_data, stream_user_data);
}
static int h3_conn_stream_close(nghttp3_conn *h3conn, int64_t stream_id,
uint64_t app_error_code,
void *conn_user_data, void *stream_user_data)
{
int ret = 0;
OSSL_DEMO_H3_CONN *conn = conn_user_data;
OSSL_DEMO_H3_STREAM *stream = stream_user_data;
if (conn->stream_close_cb != NULL)
ret = conn->stream_close_cb(h3conn, stream_id, app_error_code,
conn_user_data, stream_user_data);
h3_conn_remove_stream(conn, stream);
return ret;
}
static int h3_conn_stop_sending(nghttp3_conn *h3conn, int64_t stream_id,
uint64_t app_error_code,
void *conn_user_data, void *stream_user_data)
{
int ret = 0;
OSSL_DEMO_H3_CONN *conn = conn_user_data;
OSSL_DEMO_H3_STREAM *stream = stream_user_data;
if (conn->stop_sending_cb != NULL)
ret = conn->stop_sending_cb(h3conn, stream_id, app_error_code,
conn_user_data, stream_user_data);
SSL_free(stream->s);
stream->s = NULL;
return ret;
}
static int h3_conn_reset_stream(nghttp3_conn *h3conn, int64_t stream_id,
uint64_t app_error_code,
void *conn_user_data, void *stream_user_data)
{
int ret = 0;
OSSL_DEMO_H3_CONN *conn = conn_user_data;
OSSL_DEMO_H3_STREAM *stream = stream_user_data;
SSL_STREAM_RESET_ARGS args = {0};
if (conn->reset_stream_cb != NULL)
ret = conn->reset_stream_cb(h3conn, stream_id, app_error_code,
conn_user_data, stream_user_data);
if (stream->s != NULL) {
args.quic_error_code = app_error_code;
if (!SSL_stream_reset(stream->s, &args, sizeof(args)))
return 1;
}
return ret;
}
static int h3_conn_deferred_consume(nghttp3_conn *h3conn, int64_t stream_id,
size_t consumed,
void *conn_user_data, void *stream_user_data)
{
int ret = 0;
OSSL_DEMO_H3_CONN *conn = conn_user_data;
if (conn->deferred_consume_cb != NULL)
ret = conn->deferred_consume_cb(h3conn, stream_id, consumed,
conn_user_data, stream_user_data);
conn->consumed_app_data += consumed;
return ret;
}
OSSL_DEMO_H3_CONN *OSSL_DEMO_H3_CONN_new_for_conn(BIO *qconn_bio,
const nghttp3_callbacks *callbacks,
const nghttp3_settings *settings,
void *user_data)
{
int ec;
OSSL_DEMO_H3_CONN *conn;
OSSL_DEMO_H3_STREAM *s_ctl_send = NULL;
OSSL_DEMO_H3_STREAM *s_qpenc_send = NULL;
OSSL_DEMO_H3_STREAM *s_qpdec_send = NULL;
nghttp3_settings dsettings = {0};
nghttp3_callbacks intl_callbacks = {0};
static const unsigned char alpn[] = {2, 'h', '3'};
if (qconn_bio == NULL) {
ERR_raise_data(ERR_LIB_USER, ERR_R_PASSED_NULL_PARAMETER,
"QUIC connection BIO must be provided");
return NULL;
}
if ((conn = OPENSSL_zalloc(sizeof(OSSL_DEMO_H3_CONN))) == NULL)
return NULL;
conn->qconn_bio = qconn_bio;
conn->user_data = user_data;
if (BIO_get_ssl(qconn_bio, &conn->qconn) == 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_PASSED_INVALID_ARGUMENT,
"BIO must be an SSL BIO");
goto err;
}
/* Create the map of stream IDs to OSSL_DEMO_H3_STREAM structures. */
if ((conn->streams = lh_OSSL_DEMO_H3_STREAM_new(h3_stream_hash, h3_stream_eq)) == NULL)
goto err;
/*
* If the application has not started connecting yet, helpfully
* auto-configure ALPN. If the application wants to initiate the connection
* itself, it must take care of this itself.
*/
if (SSL_in_before(conn->qconn))
if (SSL_set_alpn_protos(conn->qconn, alpn, sizeof(alpn))) {
/* SSL_set_alpn_protos returns 1 on failure */
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"failed to configure ALPN");
goto err;
}
/*
* We use the QUIC stack in non-blocking mode so that we can react to
* incoming data on different streams, and e.g. incoming streams initiated
* by a server, as and when events occur.
*/
BIO_set_nbio(conn->qconn_bio, 1);
/*
* Disable default stream mode and create all streams explicitly. Each QUIC
* stream will be represented by its own QUIC stream SSL object (QSSO). This
* also automatically enables us to accept incoming streams (see
* SSL_set_incoming_stream_policy(3)).
*/
if (!SSL_set_default_stream_mode(conn->qconn, SSL_DEFAULT_STREAM_MODE_NONE)) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"failed to configure default stream mode");
goto err;
}
/*
* HTTP/3 requires a couple of unidirectional management streams: a control
* stream and some QPACK state management streams for each side of a
* connection. These are the instances on our side (with us sending); the
* server will also create its own equivalent unidirectional streams on its
* side, which we handle subsequently as they come in (see SSL_accept_stream
* in the event handling code below).
*/
if ((s_ctl_send
= h3_conn_create_stream(conn, OSSL_DEMO_H3_STREAM_TYPE_CTRL_SEND)) == NULL)
goto err;
if ((s_qpenc_send
= h3_conn_create_stream(conn, OSSL_DEMO_H3_STREAM_TYPE_QPACK_ENC_SEND)) == NULL)
goto err;
if ((s_qpdec_send
= h3_conn_create_stream(conn, OSSL_DEMO_H3_STREAM_TYPE_QPACK_DEC_SEND)) == NULL)
goto err;
if (settings == NULL) {
nghttp3_settings_default(&dsettings);
settings = &dsettings;
}
if (callbacks != NULL)
intl_callbacks = *callbacks;
/*
* We need to do some of our own processing when many of these events occur,
* so we note the original callback functions and forward appropriately.
*/
conn->recv_data_cb = intl_callbacks.recv_data;
conn->stream_close_cb = intl_callbacks.stream_close;
conn->stop_sending_cb = intl_callbacks.stop_sending;
conn->reset_stream_cb = intl_callbacks.reset_stream;
conn->deferred_consume_cb = intl_callbacks.deferred_consume;
intl_callbacks.recv_data = h3_conn_recv_data;
intl_callbacks.stream_close = h3_conn_stream_close;
intl_callbacks.stop_sending = h3_conn_stop_sending;
intl_callbacks.reset_stream = h3_conn_reset_stream;
intl_callbacks.deferred_consume = h3_conn_deferred_consume;
/* Create the HTTP/3 client state. */
ec = nghttp3_conn_client_new(&conn->h3conn, &intl_callbacks, settings,
NULL, conn);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot create nghttp3 connection: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
/*
* Tell the HTTP/3 stack which stream IDs are used for our outgoing control
* and QPACK streams. Note that we don't have to tell the HTTP/3 stack what
* IDs are used for incoming streams as this is inferred automatically from
* the stream type byte which starts every incoming unidirectional stream,
* so it will autodetect the correct stream IDs for the incoming control and
* QPACK streams initiated by the server.
*/
ec = nghttp3_conn_bind_control_stream(conn->h3conn, s_ctl_send->id);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot bind nghttp3 control stream: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
ec = nghttp3_conn_bind_qpack_streams(conn->h3conn,
s_qpenc_send->id,
s_qpdec_send->id);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot bind nghttp3 QPACK streams: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
return conn;
err:
nghttp3_conn_del(conn->h3conn);
h3_stream_free(s_ctl_send);
h3_stream_free(s_qpenc_send);
h3_stream_free(s_qpdec_send);
lh_OSSL_DEMO_H3_STREAM_free(conn->streams);
OPENSSL_free(conn);
return NULL;
}
OSSL_DEMO_H3_CONN *OSSL_DEMO_H3_CONN_new_for_addr(SSL_CTX *ctx, const char *addr,
const nghttp3_callbacks *callbacks,
const nghttp3_settings *settings,
void *user_data)
{
BIO *qconn_bio = NULL;
SSL *qconn = NULL;
OSSL_DEMO_H3_CONN *conn = NULL;
const char *bare_hostname;
/* QUIC connection setup */
if ((qconn_bio = BIO_new_ssl_connect(ctx)) == NULL)
goto err;
/* Pass the 'hostname:port' string into the ssl_connect BIO. */
if (BIO_set_conn_hostname(qconn_bio, addr) == 0)
goto err;
/*
* Get the 'bare' hostname out of the ssl_connect BIO. This is the hostname
* without the port.
*/
bare_hostname = BIO_get_conn_hostname(qconn_bio);
if (bare_hostname == NULL)
goto err;
if (BIO_get_ssl(qconn_bio, &qconn) == 0)
goto err;
/* Set the hostname we will validate the X.509 certificate against. */
if (SSL_set1_host(qconn, bare_hostname) <= 0)
goto err;
/* Configure SNI */
if (!SSL_set_tlsext_host_name(qconn, bare_hostname))
goto err;
conn = OSSL_DEMO_H3_CONN_new_for_conn(qconn_bio, callbacks,
settings, user_data);
if (conn == NULL)
goto err;
return conn;
err:
BIO_free_all(qconn_bio);
return NULL;
}
int OSSL_DEMO_H3_CONN_connect(OSSL_DEMO_H3_CONN *conn)
{
return SSL_connect(OSSL_DEMO_H3_CONN_get0_connection(conn));
}
void *OSSL_DEMO_H3_CONN_get_user_data(const OSSL_DEMO_H3_CONN *conn)
{
return conn->user_data;
}
SSL *OSSL_DEMO_H3_CONN_get0_connection(const OSSL_DEMO_H3_CONN *conn)
{
return conn->qconn;
}
/* Pumps received data to the HTTP/3 stack for a single stream. */
static void h3_conn_pump_stream(OSSL_DEMO_H3_STREAM *s, void *conn_)
{
int ec;
OSSL_DEMO_H3_CONN *conn = conn_;
size_t num_bytes, consumed;
uint64_t aec;
if (!conn->pump_res)
/*
* Handling of a previous stream in the iteration over all streams
* failed, so just do nothing.
*/
return;
for (;;) {
if (s->s == NULL /* If we already did STOP_SENDING, ignore this stream. */
/* If this is a write-only stream, there is no read data to check. */
|| SSL_get_stream_read_state(s->s) == SSL_STREAM_STATE_WRONG_DIR
/*
* If we already got a FIN for this stream, there is nothing more to
* do for it.
*/
|| s->done_recv_fin)
break;
/*
* Pump data from OpenSSL QUIC to the HTTP/3 stack by calling SSL_peek
* to get received data and passing it to nghttp3 using
* nghttp3_conn_read_stream. Note that this function is confusingly
* named and inputs data to the HTTP/3 stack.
*/
if (s->buf_cur == s->buf_total) {
/* Need more data. */
ec = SSL_read_ex(s->s, s->buf, sizeof(s->buf), &num_bytes);
if (ec <= 0) {
num_bytes = 0;
if (SSL_get_error(s->s, ec) == SSL_ERROR_ZERO_RETURN) {
/* Stream concluded normally. Pass FIN to HTTP/3 stack. */
ec = nghttp3_conn_read_stream(conn->h3conn, s->id, NULL, 0,
/*fin=*/1);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot pass FIN to nghttp3: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
s->done_recv_fin = 1;
} else if (SSL_get_stream_read_state(s->s)
== SSL_STREAM_STATE_RESET_REMOTE) {
/* Stream was reset by peer. */
if (!SSL_get_stream_read_error_code(s->s, &aec))
goto err;
ec = nghttp3_conn_close_stream(conn->h3conn, s->id, aec);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot mark stream as reset: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
s->done_recv_fin = 1;
} else {
/* Other error. */
goto err;
}
}
s->buf_cur = 0;
s->buf_total = num_bytes;
}
if (s->buf_cur == s->buf_total)
break;
/*
* This function is confusingly named as it is is named from nghttp3's
* 'perspective'; it is used to pass data *into* the HTTP/3 stack which
* has been received from the network.
*/
assert(conn->consumed_app_data == 0);
ec = nghttp3_conn_read_stream(conn->h3conn, s->id, s->buf + s->buf_cur,
s->buf_total - s->buf_cur, /*fin=*/0);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"nghttp3 failed to process incoming data: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
/*
* read_stream reports the data it consumes from us in two different
* ways; the non-application data is returned as a number of bytes 'ec'
* above, but the number of bytes of application data has to be recorded
* by our callback. We sum the two to determine the total number of
* bytes which nghttp3 consumed.
*/
consumed = ec + conn->consumed_app_data;
assert(consumed <= s->buf_total - s->buf_cur);
s->buf_cur += consumed;
conn->consumed_app_data = 0;
}
return;
err:
conn->pump_res = 0;
}
int OSSL_DEMO_H3_CONN_handle_events(OSSL_DEMO_H3_CONN *conn)
{
int ec, fin;
size_t i, num_vecs, written, total_written, total_len;
int64_t stream_id;
uint64_t flags;
nghttp3_vec vecs[8] = {0};
OSSL_DEMO_H3_STREAM key, *s;
SSL *snew;
if (conn == NULL)
return 0;
/*
* We handle events by doing three things:
*
* 1. Handle new incoming streams
* 2. Pump outgoing data from the HTTP/3 stack to the QUIC engine
* 3. Pump incoming data from the QUIC engine to the HTTP/3 stack
*/
/* 1. Check for new incoming streams */
for (;;) {
if ((snew = SSL_accept_stream(conn->qconn, SSL_ACCEPT_STREAM_NO_BLOCK)) == NULL)
break;
/*
* Each new incoming stream gets wrapped into an OSSL_DEMO_H3_STREAM object and
* added into our stream ID map.
*/
if (h3_conn_accept_stream(conn, snew) == NULL) {
SSL_free(snew);
return 0;
}
}
/* 2. Pump outgoing data from HTTP/3 engine to QUIC. */
for (;;) {
/*
* Get a number of send vectors from the HTTP/3 engine.
*
* Note that this function is confusingly named as it is named from
* nghttp3's 'perspective': this outputs pointers to data which nghttp3
* wants to *write* to the network.
*/
ec = nghttp3_conn_writev_stream(conn->h3conn, &stream_id, &fin,
vecs, ARRAY_LEN(vecs));
if (ec < 0)
return 0;
if (ec == 0)
break;
/*
* we let SSL_write_ex2(3) to conclude the stream for us (send FIN)
* after all data are written.
*/
flags = (fin == 0) ? 0 : SSL_WRITE_FLAG_CONCLUDE;
/* For each of the vectors returned, pass it to OpenSSL QUIC. */
key.id = stream_id;
if ((s = lh_OSSL_DEMO_H3_STREAM_retrieve(conn->streams, &key)) == NULL) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"no stream for ID %zd", stream_id);
return 0;
}
num_vecs = ec;
total_len = nghttp3_vec_len(vecs, num_vecs);
total_written = 0;
for (i = 0; i < num_vecs; ++i) {
if (vecs[i].len == 0)
continue;
if (s->s == NULL) {
/* Already did STOP_SENDING and threw away stream, ignore */
written = vecs[i].len;
} else if (!SSL_write_ex2(s->s, vecs[i].base, vecs[i].len, flags, &written)) {
if (SSL_get_error(s->s, 0) == SSL_ERROR_WANT_WRITE) {
/*
* We have filled our send buffer so tell nghttp3 to stop
* generating more data; we have to do this explicitly.
*/
written = 0;
nghttp3_conn_block_stream(conn->h3conn, stream_id);
} else {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"writing HTTP/3 data to network failed");
return 0;
}
} else {
/*
* Tell nghttp3 it can resume generating more data in case we
* previously called block_stream.
*/
nghttp3_conn_unblock_stream(conn->h3conn, stream_id);
}
total_written += written;
if (written > 0) {
/*
* Tell nghttp3 we have consumed the data it output when we
* called writev_stream, otherwise subsequent calls to
* writev_stream will output the same data.
*/
ec = nghttp3_conn_add_write_offset(conn->h3conn, stream_id, written);
if (ec < 0)
return 0;
/*
* Tell nghttp3 it can free the buffered data because we will
* not need it again. In our case we can always do this right
* away because we copy the data into our QUIC send buffers
* rather than simply storing a reference to it.
*/
ec = nghttp3_conn_add_ack_offset(conn->h3conn, stream_id, written);
if (ec < 0)
return 0;
}
}
if (fin && total_written == total_len) {
if (total_len == 0) {
/*
* As a special case, if nghttp3 requested to write a
* zero-length stream with a FIN, we have to tell it we did this
* by calling add_write_offset(0).
*/
ec = nghttp3_conn_add_write_offset(conn->h3conn, stream_id, 0);
if (ec < 0)
return 0;
}
}
}
/* 3. Pump incoming data from QUIC to HTTP/3 engine. */
conn->pump_res = 1; /* cleared in below call if an error occurs */
lh_OSSL_DEMO_H3_STREAM_doall_arg(conn->streams, h3_conn_pump_stream, conn);
if (!conn->pump_res)
return 0;
return 1;
}
int OSSL_DEMO_H3_CONN_submit_request(OSSL_DEMO_H3_CONN *conn,
const nghttp3_nv *nva, size_t nvlen,
const nghttp3_data_reader *dr,
void *user_data)
{
int ec;
OSSL_DEMO_H3_STREAM *s_req = NULL;
if (conn == NULL) {
ERR_raise_data(ERR_LIB_USER, ERR_R_PASSED_NULL_PARAMETER,
"connection must be specified");
return 0;
}
/* Each HTTP/3 request is represented by a stream. */
if ((s_req = h3_conn_create_stream(conn, OSSL_DEMO_H3_STREAM_TYPE_REQ)) == NULL)
goto err;
s_req->user_data = user_data;
ec = nghttp3_conn_submit_request(conn->h3conn, s_req->id, nva, nvlen,
dr, s_req);
if (ec < 0) {
ERR_raise_data(ERR_LIB_USER, ERR_R_INTERNAL_ERROR,
"cannot submit HTTP/3 request: %s (%d)",
nghttp3_strerror(ec), ec);
goto err;
}
return 1;
err:
h3_conn_remove_stream(conn, s_req);
return 0;
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef OSSL_NGHTTP3_H
# define OSSL_NGHTTP3_H
# include <openssl/bio.h>
# include <openssl/ssl.h>
# include <nghttp3/nghttp3.h>
/*
* ossl-nghttp3: Demo binding of nghttp3 to OpenSSL QUIC
* =====================================================
*
* This is a simple library which provides an example binding of the nghttp3
* HTTP/3 library to OpenSSL's QUIC API.
*/
/* Represents an HTTP/3 connection to a server. */
typedef struct ossl_demo_h3_conn_st OSSL_DEMO_H3_CONN;
/* Represents an HTTP/3 request, control or QPACK stream. */
typedef struct ossl_demo_h3_stream_st OSSL_DEMO_H3_STREAM;
/*
* Creates a HTTP/3 connection using the given QUIC client connection BIO. The
* BIO must be able to provide an SSL object pointer using BIO_get_ssl. Takes
* ownership of the reference. If the QUIC connection SSL object has not already
* been connected, HTTP/3 ALPN is set automatically. If it has already been
* connected, HTTP/3 ALPN ("h3") must have been configured and no streams must
* have been created yet.
*
* If settings is NULL, use default settings only. Settings unsupported by
* this QUIC binding are ignored.
*
* user_data is an application-provided opaque value which can be retrieved
* using OSSL_DEMO_H3_CONN_get_user_data. Note that the user data value passed
* to the callback functions specified in callbacks is a pointer to the
* OSSL_DEMO_H3_CONN, not user_data.
*
* Returns NULL on failure.
*/
OSSL_DEMO_H3_CONN *OSSL_DEMO_H3_CONN_new_for_conn(BIO *qconn_bio,
const nghttp3_callbacks *callbacks,
const nghttp3_settings *settings,
void *user_data);
/*
* Works identically to OSSL_DEMO_H3_CONN_new_for_conn except that it manages
* the creation of a QUIC connection SSL object automatically using an address
* string. addr should be a string such as "www.example.com:443". The created
* underlying QUIC connection SSL object is owned by the OSSL_DEMO_H3_CONN and
* can be subsequently retrieved using OSSL_DEMO_H3_CONN_get0_connection.
*
* Returns NULL on failure. ctx must be a SSL_CTX using a QUIC client
* SSL_METHOD.
*/
OSSL_DEMO_H3_CONN *OSSL_DEMO_H3_CONN_new_for_addr(SSL_CTX *ctx,
const char *addr,
const nghttp3_callbacks *callbacks,
const nghttp3_settings *settings,
void *user_data);
/* Equivalent to SSL_connect(OSSL_DEMO_H3_CONN_get0_connection(conn)). */
int OSSL_DEMO_H3_CONN_connect(OSSL_DEMO_H3_CONN *conn);
/*
* Free the OSSL_DEMO_H3_CONN and any underlying QUIC connection SSL object and
* associated streams.
*/
void OSSL_DEMO_H3_CONN_free(OSSL_DEMO_H3_CONN *conn);
/*
* Returns the user data value which was specified in
* OSSL_DEMO_H3_CONN_new_for_conn.
*/
void *OSSL_DEMO_H3_CONN_get_user_data(const OSSL_DEMO_H3_CONN *conn);
/* Returns the underlying QUIC connection SSL object. */
SSL *OSSL_DEMO_H3_CONN_get0_connection(const OSSL_DEMO_H3_CONN *conn);
/*
* Handle any pending events on a given HTTP/3 connection. Returns 0 on error.
*/
int OSSL_DEMO_H3_CONN_handle_events(OSSL_DEMO_H3_CONN *conn);
/*
* Submits a new HTTP/3 request on the given connection. Returns 0 on error.
*
* This works analogously to nghttp3_conn_submit_request(). The stream user data
* pointer passed to the callbacks is a OSSL_DEMO_H3_STREAM object pointer; to
* retrieve the stream user data pointer passed to this function, use
* OSSL_DEMO_H3_STREAM_get_user_data.
*/
int OSSL_DEMO_H3_CONN_submit_request(OSSL_DEMO_H3_CONN *conn,
const nghttp3_nv *hdr, size_t hdrlen,
const nghttp3_data_reader *dr,
void *stream_user_data);
/*
* Returns the user data value which was specified in
* OSSL_DEMO_H3_CONN_submit_request.
*/
void *OSSL_DEMO_H3_STREAM_get_user_data(const OSSL_DEMO_H3_STREAM *stream);
#endif

View File

@@ -0,0 +1,35 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./hkdf
TESTS = hkdf \
pbkdf2 \
scrypt \
argon2
CFLAGS = -I../../include -g -Wall
LDFLAGS = -L../..
LDLIBS = -lcrypto
all: $(TESTS)
hkdf: hkdf.o
pbkdf2: pbkdf2.o
scrypt: scrypt.o
argon2: argon2.o
$(TESTS):
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS)
clean:
$(RM) *.o $(TESTS)
.PHONY: test
test: all
@echo "\nKDF tests:"
@set -e; for tst in $(TESTS); do \
echo "\n"$$tst; \
LD_LIBRARY_PATH=../.. ./$$tst; \
done

View File

@@ -0,0 +1,156 @@
/*
* Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/kdf.h>
#include <openssl/params.h>
#include <openssl/thread.h>
/*
* Example showing how to use Argon2 KDF.
* See man EVP_KDF-ARGON2 for more information.
*
* test vector from
* https://datatracker.ietf.org/doc/html/rfc9106
*/
/*
* Hard coding a password into an application is very bad.
* It is done here solely for educational purposes.
*/
static unsigned char password[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
};
/*
* The salt is better not being hard coded too. Each password should have a
* different salt if possible. The salt is not considered secret information
* and is safe to store with an encrypted password.
*/
static unsigned char salt[] = {
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
};
/*
* Optional secret for KDF
*/
static unsigned char secret[] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
};
/*
* Optional additional data
*/
static unsigned char ad[] = {
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04
};
/*
* Argon2 cost parameters
*/
static uint32_t memory_cost = 32;
static uint32_t iteration_cost = 3;
static uint32_t parallel_cost = 4;
static const unsigned char expected_output[] = {
0x0d, 0x64, 0x0d, 0xf5, 0x8d, 0x78, 0x76, 0x6c,
0x08, 0xc0, 0x37, 0xa3, 0x4a, 0x8b, 0x53, 0xc9,
0xd0, 0x1e, 0xf0, 0x45, 0x2d, 0x75, 0xb6, 0x5e,
0xb5, 0x25, 0x20, 0xe9, 0x6b, 0x01, 0xe6, 0x59
};
int main(int argc, char **argv)
{
int rv = EXIT_FAILURE;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[32];
OSSL_PARAM params[9], *p = params;
OSSL_LIB_CTX *library_context = NULL;
unsigned int threads;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto end;
}
/* Fetch the key derivation function implementation */
kdf = EVP_KDF_fetch(library_context, "argon2id", NULL);
if (kdf == NULL) {
fprintf(stderr, "EVP_KDF_fetch() returned NULL\n");
goto end;
}
/* Create a context for the key derivation operation */
kctx = EVP_KDF_CTX_new(kdf);
if (kctx == NULL) {
fprintf(stderr, "EVP_KDF_CTX_new() returned NULL\n");
goto end;
}
/*
* Thread support can be turned off; use serialization if we cannot
* set requested number of threads.
*/
threads = parallel_cost;
if (OSSL_set_max_threads(library_context, parallel_cost) != 1) {
uint64_t max_threads = OSSL_get_max_threads(library_context);
if (max_threads == 0)
threads = 1;
else if (max_threads < parallel_cost)
threads = max_threads;
}
/* Set password */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, password, sizeof(password));
/* Set salt */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, salt, sizeof(salt));
/* Set optional additional data */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_ARGON2_AD, ad, sizeof(ad));
/* Set optional secret */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SECRET, secret, sizeof(secret));
/* Set iteration count */
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ITER, &iteration_cost);
/* Set threads performing derivation (can be decreased) */
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_THREADS, &threads);
/* Set parallel cost */
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &parallel_cost);
/* Set memory requirement */
*p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memory_cost);
*p = OSSL_PARAM_construct_end();
/* Derive the key */
if (EVP_KDF_derive(kctx, out, sizeof(out), params) != 1) {
fprintf(stderr, "EVP_KDF_derive() failed\n");
goto end;
}
if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) {
fprintf(stderr, "Generated key does not match expected value\n");
goto end;
}
printf("Success\n");
rv = EXIT_SUCCESS;
end:
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
OSSL_LIB_CTX_free(library_context);
return rv;
}

View File

@@ -0,0 +1,26 @@
#
# To run the demos when linked with a shared library (default) ensure that
# libcrypto is on the library path. For example:
#
# LD_LIBRARY_PATH=../.. ./hkdf
PROGRAMS{noinst} = hkdf \
pbkdf2 \
scrypt \
argon2
INCLUDE[hkdf]=../../include
SOURCE[hkdf]=hkdf.c
DEPEND[hkdf]=../../libcrypto
INCLUDE[pbkdf2]=../../include
SOURCE[pbkdf2]=pbkdf2.c
DEPEND[pbkdf2]=../../libcrypto
INCLUDE[scrypt]=../../include
SOURCE[scrypt]=scrypt.c
DEPEND[scrypt]=../../libcrypto
INCLUDE[argon2]=../../include
SOURCE[argon2]=argon2.c
DEPEND[argon2]=../../libcrypto

View File

@@ -0,0 +1,106 @@
/*
* Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/kdf.h>
#include <openssl/obj_mac.h>
#include <openssl/params.h>
/*
* test vector from
* https://datatracker.ietf.org/doc/html/rfc5869
*/
static unsigned char hkdf_salt[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c
};
static unsigned char hkdf_ikm[] = {
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
};
static unsigned char hkdf_info[] = {
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9
};
/* Expected output keying material */
static unsigned char hkdf_okm[] = {
0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64,
0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08,
0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65
};
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[42];
OSSL_PARAM params[5], *p = params;
OSSL_LIB_CTX *library_context = NULL;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto end;
}
/* Fetch the key derivation function implementation */
kdf = EVP_KDF_fetch(library_context, "HKDF", NULL);
if (kdf == NULL) {
fprintf(stderr, "EVP_KDF_fetch() returned NULL\n");
goto end;
}
/* Create a context for the key derivation operation */
kctx = EVP_KDF_CTX_new(kdf);
if (kctx == NULL) {
fprintf(stderr, "EVP_KDF_CTX_new() returned NULL\n");
goto end;
}
/* Set the underlying hash function used to derive the key */
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
"SHA256", 0);
/* Set input keying material */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, hkdf_ikm,
sizeof(hkdf_ikm));
/* Set application specific information */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, hkdf_info,
sizeof(hkdf_info));
/* Set salt */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, hkdf_salt,
sizeof(hkdf_salt));
*p = OSSL_PARAM_construct_end();
/* Derive the key */
if (EVP_KDF_derive(kctx, out, sizeof(out), params) != 1) {
fprintf(stderr, "EVP_KDF_derive() failed\n");
goto end;
}
if (CRYPTO_memcmp(hkdf_okm, out, sizeof(hkdf_okm)) != 0) {
fprintf(stderr, "Generated key does not match expected value\n");
goto end;
}
printf("Success\n");
ret = EXIT_SUCCESS;
end:
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
OSSL_LIB_CTX_free(library_context);
return ret;
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/kdf.h>
#include <openssl/obj_mac.h>
#include <openssl/params.h>
/*
* test vector from
* https://datatracker.ietf.org/doc/html/rfc7914
*/
/*
* Hard coding a password into an application is very bad.
* It is done here solely for educational purposes.
*/
static unsigned char password[] = {
'P', 'a', 's', 's', 'w', 'o', 'r', 'd'
};
/*
* The salt is better not being hard coded too. Each password should have a
* different salt if possible. The salt is not considered secret information
* and is safe to store with an encrypted password.
*/
static unsigned char pbkdf2_salt[] = {
'N', 'a', 'C', 'l'
};
/*
* The iteration parameter can be variable or hard coded. The disadvantage with
* hard coding them is that they cannot easily be adjusted for future
* technological improvements appear.
*/
static unsigned int pbkdf2_iterations = 80000;
static const unsigned char expected_output[] = {
0x4d, 0xdc, 0xd8, 0xf6, 0x0b, 0x98, 0xbe, 0x21,
0x83, 0x0c, 0xee, 0x5e, 0xf2, 0x27, 0x01, 0xf9,
0x64, 0x1a, 0x44, 0x18, 0xd0, 0x4c, 0x04, 0x14,
0xae, 0xff, 0x08, 0x87, 0x6b, 0x34, 0xab, 0x56,
0xa1, 0xd4, 0x25, 0xa1, 0x22, 0x58, 0x33, 0x54,
0x9a, 0xdb, 0x84, 0x1b, 0x51, 0xc9, 0xb3, 0x17,
0x6a, 0x27, 0x2b, 0xde, 0xbb, 0xa1, 0xd0, 0x78,
0x47, 0x8f, 0x62, 0xb3, 0x97, 0xf3, 0x3c, 0x8d
};
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[64];
OSSL_PARAM params[5], *p = params;
OSSL_LIB_CTX *library_context = NULL;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto end;
}
/* Fetch the key derivation function implementation */
kdf = EVP_KDF_fetch(library_context, "PBKDF2", NULL);
if (kdf == NULL) {
fprintf(stderr, "EVP_KDF_fetch() returned NULL\n");
goto end;
}
/* Create a context for the key derivation operation */
kctx = EVP_KDF_CTX_new(kdf);
if (kctx == NULL) {
fprintf(stderr, "EVP_KDF_CTX_new() returned NULL\n");
goto end;
}
/* Set password */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, password,
sizeof(password));
/* Set salt */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, pbkdf2_salt,
sizeof(pbkdf2_salt));
/* Set iteration count (default 2048) */
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_ITER, &pbkdf2_iterations);
/* Set the underlying hash function used to derive the key */
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
"SHA256", 0);
*p = OSSL_PARAM_construct_end();
/* Derive the key */
if (EVP_KDF_derive(kctx, out, sizeof(out), params) != 1) {
fprintf(stderr, "EVP_KDF_derive() failed\n");
goto end;
}
if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) {
fprintf(stderr, "Generated key does not match expected value\n");
goto end;
}
printf("Success\n");
ret = EXIT_SUCCESS;
end:
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
OSSL_LIB_CTX_free(library_context);
return ret;
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2021-2023 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/kdf.h>
#include <openssl/obj_mac.h>
#include <openssl/params.h>
/*
* test vector from
* https://datatracker.ietf.org/doc/html/rfc7914
*/
/*
* Hard coding a password into an application is very bad.
* It is done here solely for educational purposes.
*/
static unsigned char password[] = {
'p', 'a', 's', 's', 'w', 'o', 'r', 'd'
};
/*
* The salt is better not being hard coded too. Each password should have a
* different salt if possible. The salt is not considered secret information
* and is safe to store with an encrypted password.
*/
static unsigned char scrypt_salt[] = {
'N', 'a', 'C', 'l'
};
/*
* The SCRYPT parameters can be variable or hard coded. The disadvantage with
* hard coding them is that they cannot easily be adjusted for future
* technological improvements appear.
*/
static unsigned int scrypt_n = 1024;
static unsigned int scrypt_r = 8;
static unsigned int scrypt_p = 16;
static const unsigned char expected_output[] = {
0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
};
int main(int argc, char **argv)
{
int ret = EXIT_FAILURE;
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *kctx = NULL;
unsigned char out[64];
OSSL_PARAM params[6], *p = params;
OSSL_LIB_CTX *library_context = NULL;
library_context = OSSL_LIB_CTX_new();
if (library_context == NULL) {
fprintf(stderr, "OSSL_LIB_CTX_new() returned NULL\n");
goto end;
}
/* Fetch the key derivation function implementation */
kdf = EVP_KDF_fetch(library_context, "SCRYPT", NULL);
if (kdf == NULL) {
fprintf(stderr, "EVP_KDF_fetch() returned NULL\n");
goto end;
}
/* Create a context for the key derivation operation */
kctx = EVP_KDF_CTX_new(kdf);
if (kctx == NULL) {
fprintf(stderr, "EVP_KDF_CTX_new() returned NULL\n");
goto end;
}
/* Set password */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, password,
sizeof(password));
/* Set salt */
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, scrypt_salt,
sizeof(scrypt_salt));
/* Set N (default 1048576) */
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_N, &scrypt_n);
/* Set R (default 8) */
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_R, &scrypt_r);
/* Set P (default 1) */
*p++ = OSSL_PARAM_construct_uint(OSSL_KDF_PARAM_SCRYPT_P, &scrypt_p);
*p = OSSL_PARAM_construct_end();
/* Derive the key */
if (EVP_KDF_derive(kctx, out, sizeof(out), params) != 1) {
fprintf(stderr, "EVP_KDF_derive() failed\n");
goto end;
}
if (CRYPTO_memcmp(expected_output, out, sizeof(expected_output)) != 0) {
fprintf(stderr, "Generated key does not match expected value\n");
goto end;
}
printf("Success\n");
ret = EXIT_SUCCESS;
end:
EVP_KDF_CTX_free(kctx);
EVP_KDF_free(kdf);
OSSL_LIB_CTX_free(library_context);
return ret;
}

Some files were not shown because too many files have changed in this diff Show More