Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement Delegated Credentials #37

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ IF (OPENSSL_FOUND AND NOT (OPENSSL_VERSION VERSION_LESS "1.0.1"))
ADD_LIBRARY(picotls-openssl lib/openssl.c)
ADD_EXECUTABLE(cli t/cli.c)
TARGET_LINK_LIBRARIES(cli picotls-openssl picotls-core ${OPENSSL_LIBRARIES})
ADD_EXECUTABLE(delcred t/delcred.c)
TARGET_LINK_LIBRARIES(delcred picotls-openssl picotls-core ${OPENSSL_LIBRARIES})
ADD_EXECUTABLE(test-openssl.t ${MINICRYPTO_LIBRARY_FILES} lib/cifra.c lib/uecc.c deps/picotest/picotest.c t/picotls.c t/openssl.c)
SET_TARGET_PROPERTIES(test-openssl.t PROPERTIES COMPILE_FLAGS "-DPTLS_MEMORY_DEBUG=1")
TARGET_LINK_LIBRARIES(test-openssl.t ${OPENSSL_LIBRARIES})
Expand Down
22 changes: 21 additions & 1 deletion include/picotls.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ typedef struct st_ptls_hash_context_t {
struct st_ptls_hash_context_t *(*clone_)(struct st_ptls_hash_context_t *src);
} ptls_hash_context_t;

typedef struct st_ptls_delegated_credential_t {
uint16_t protocol_version;
uint32_t valid_time;
ptls_iovec_t public_key;
uint16_t signature_scheme;
ptls_iovec_t signature;
} ptls_delegated_credential_t;

/**
* A hash algorithm and its properties.
*/
Expand Down Expand Up @@ -273,7 +281,7 @@ PTLS_CALLBACK_TYPE(int, sign_certificate, ptls_t *tls, uint16_t *selected_algori
*/
PTLS_CALLBACK_TYPE(int, verify_certificate, ptls_t *tls,
int (**verify_sign)(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t sign), void **verify_data,
ptls_iovec_t *certs, size_t num_certs);
ptls_iovec_t *certs, size_t num_certs, ptls_delegated_credential_t *delegated_cred);
/**
* encrypt-and-signs (or verify-and-decrypts) a ticket (server-only)
*/
Expand Down Expand Up @@ -313,6 +321,7 @@ typedef struct st_ptls_context_t {
struct {
ptls_iovec_t *list;
size_t count;
ptls_iovec_t delegated_credential;
} certificates;
/**
*
Expand Down Expand Up @@ -593,6 +602,17 @@ void ptls_aead_free(ptls_aead_context_t *ctx);
*/
int ptls_aead_transform(ptls_aead_context_t *ctx, void *output, size_t *outlen, const void *input, size_t inlen,
uint8_t enc_content_type);
/**
*
*/
int ptls_sign_delegated_credential(ptls_sign_certificate_t *self, ptls_buffer_t *output, ptls_delegated_credential_t *input,
ptls_iovec_t signer_cert);
/**
*
*/
int ptls_verify_delegated_credential(int (*verify_sign)(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t sign), void *verify_ctx,
ptls_delegated_credential_t *cred, ptls_iovec_t signer_cert);

/**
* clears memory
*/
Expand Down
24 changes: 23 additions & 1 deletion lib/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,11 @@ static int sign_certificate(ptls_sign_certificate_t *_self, ptls_t *tls, uint16_

Found:
*selected_algorithm = scheme->scheme_id;

/* just return the selected algorithm */
if (outbuf == NULL)
return 0;
/* do the hard work */
return do_sign(self->key, outbuf, input, scheme->scheme_md);
}

Expand Down Expand Up @@ -607,6 +612,9 @@ static int verify_sign(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t signatu
Exit:
if (ctx != NULL)
EVP_MD_CTX_destroy(ctx);
#if 0 /* FIXMEEEE */
EVP_PKEY_free(key);
#endif
return ret;
}

Expand Down Expand Up @@ -719,14 +727,16 @@ int ptls_openssl_load_certificates(ptls_context_t *ctx, X509 *cert, STACK_OF(X50
}

static int verify_certificate(ptls_verify_certificate_t *_self, ptls_t *tls, int (**verifier)(void *, ptls_iovec_t, ptls_iovec_t),
void **verify_data, ptls_iovec_t *certs, size_t num_certs)
void **verify_data, ptls_iovec_t *certs, size_t num_certs, ptls_delegated_credential_t *delegated_cred)
{
ptls_openssl_verify_certificate_t *self = (ptls_openssl_verify_certificate_t *)_self;
X509 *cert = NULL;
STACK_OF(X509) *chain = NULL;
X509_STORE_CTX *verify_ctx = NULL;
int ret = 0;

*verify_data = NULL;

assert(num_certs != 0);

if ((cert = to_x509(certs[0])) == NULL) {
Expand Down Expand Up @@ -776,9 +786,21 @@ static int verify_certificate(ptls_verify_certificate_t *_self, ptls_t *tls, int
ret = PTLS_ALERT_BAD_CERTIFICATE;
goto Exit;
}

if (delegated_cred != NULL) {
if ((ret = ptls_verify_delegated_credential(verify_sign, *verify_data, delegated_cred, certs[0])) != 0)
goto Exit;
const uint8_t *p = delegated_cred->public_key.base;
if ((*verify_data = d2i_PUBKEY(NULL, &p, delegated_cred->public_key.len)) == NULL) {
ret = PTLS_ALERT_ILLEGAL_PARAMETER;
goto Exit;
}
}
*verifier = verify_sign;

Exit:
if (ret != 0 && *verify_data != NULL)
EVP_PKEY_free(*verify_data);
if (verify_ctx != NULL)
X509_STORE_CTX_free(verify_ctx);
if (chain != NULL)
Expand Down
132 changes: 130 additions & 2 deletions lib/picotls.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
#define PTLS_EXTENSION_TYPE_COOKIE 44
#define PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES 45
#define PTLS_EXTENSION_TYPE_TICKET_EARLY_DATA_INFO 46
#define PTLS_EXTENSION_TYPE_DELEGATED_CREDENTIAL 26 /* for now */

#define PTLS_PROTOCOL_VERSION_DRAFT18 0x7f12

Expand Down Expand Up @@ -229,6 +230,7 @@ struct st_ptls_client_hello_t {
int early_data_indication;
} psk;
unsigned status_request : 1;
unsigned delegated_credential : 1;
};

struct st_ptls_server_hello_t {
Expand Down Expand Up @@ -1097,6 +1099,7 @@ static int send_client_hello(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_handshake
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SUPPORTED_VERSIONS, {
ptls_buffer_push_block(sendbuf, 1, { ptls_buffer_push16(sendbuf, PTLS_PROTOCOL_VERSION_DRAFT18); });
});
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_DELEGATED_CREDENTIAL, {});
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_SIGNATURE_ALGORITHMS, {
ptls_buffer_push_block(sendbuf, 2, {
ptls_buffer_push16(sendbuf, PTLS_SIGNATURE_RSA_PSS_SHA256);
Expand Down Expand Up @@ -1444,6 +1447,7 @@ static int client_handle_certificate(ptls_t *tls, ptls_iovec_t message)
const uint8_t *src = message.base + PTLS_HANDSHAKE_HEADER_SIZE, *end = message.base + message.len;
ptls_iovec_t certs[16];
size_t num_certs = 0;
ptls_delegated_credential_t *delegated_cred = NULL;
int ret;

/* certificate request context */
Expand All @@ -1462,13 +1466,48 @@ static int client_handle_certificate(ptls_t *tls, ptls_iovec_t message)
src = end;
});
uint16_t type;
decode_open_extensions(src, end, PTLS_HANDSHAKE_TYPE_CERTIFICATE, &type, { src = end; });
decode_open_extensions(src, end, PTLS_HANDSHAKE_TYPE_CERTIFICATE, &type, {
switch (type) {
case PTLS_EXTENSION_TYPE_DELEGATED_CREDENTIAL:
if (num_certs != 1) {
ret = PTLS_ALERT_ILLEGAL_PARAMETER;
goto Exit;
}
/* parse the credential */
if ((delegated_cred = malloc(sizeof(*delegated_cred))) == NULL) {
ret = PTLS_ERROR_NO_MEMORY;
goto Exit;
}
fprintf(stderr, "end of extension:%p\n", end);
delegated_cred->protocol_version = PTLS_PROTOCOL_VERSION_DRAFT18;
if ((ret = decode32(&delegated_cred->valid_time, &src, end)) != 0)
goto Exit;
fprintf(stderr, "****valid_time:%" PRIu32 "\n", delegated_cred->valid_time);
decode_open_block(src, end, 3, {
delegated_cred->public_key = ptls_iovec_init(src, end - src);
fprintf(stderr, "****public_key:%zu\n", delegated_cred->public_key.len);
src = end;
});
if ((ret = decode16(&delegated_cred->signature_scheme, &src, end)) != 0)
goto Exit;
fprintf(stderr, "****sigscheme:%" PRIu16 "\n", delegated_cred->signature_scheme);
decode_block(src, end, 2, {
delegated_cred->signature = ptls_iovec_init(src, end - src);
fprintf(stderr, "****signature:%zu, end:%p\n", delegated_cred->signature.len, end);
src = end;
});
break;
default:
src = end;
break;
}
});
} while (src != end);
});

if (tls->ctx->verify_certificate != NULL) {
if ((ret = tls->ctx->verify_certificate->cb(tls->ctx->verify_certificate, tls, &tls->client.certificate_verify.cb,
&tls->client.certificate_verify.verify_ctx, certs, num_certs)) != 0)
&tls->client.certificate_verify.verify_ctx, certs, num_certs, delegated_cred)) != 0)
goto Exit;
}

Expand All @@ -1477,6 +1516,7 @@ static int client_handle_certificate(ptls_t *tls, ptls_iovec_t message)
ret = PTLS_ERROR_IN_PROGRESS;

Exit:
free(delegated_cred);
return ret;
}

Expand Down Expand Up @@ -1862,6 +1902,8 @@ static int decode_client_hello(struct st_ptls_client_hello_t *ch, const uint8_t
case PTLS_EXTENSION_TYPE_STATUS_REQUEST:
ch->status_request = 1;
break;
case PTLS_EXTENSION_TYPE_DELEGATED_CREDENTIAL:
ch->delegated_credential = 1;
default:
break;
}
Expand Down Expand Up @@ -2218,6 +2260,12 @@ static int server_handle_hello(ptls_t *tls, ptls_buffer_t *sendbuf, ptls_iovec_t
if (reset_off_to != 0)
sendbuf->off = reset_off_to;
}
if (i == 0 && ch.delegated_credential && tls->ctx->certificates.delegated_credential.base != NULL) {
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_DELEGATED_CREDENTIAL, {
ptls_buffer_pushv(sendbuf, tls->ctx->certificates.delegated_credential.base,
tls->ctx->certificates.delegated_credential.len);
});
}
});
}
});
Expand Down Expand Up @@ -3045,6 +3093,86 @@ int ptls_aead_transform(ptls_aead_context_t *ctx, void *output, size_t *outlen,
return 0;
}

static int serialize_delegated_credential_params(ptls_buffer_t *output, uint32_t valid_time, ptls_iovec_t public_key)
{
int ret;

ptls_buffer_push32(output, valid_time);
ptls_buffer_push_block(output, 3, {
ptls_buffer_pushv(output, public_key.base, public_key.len);
});

ret = 0;
Exit:
return ret;
}

static int serialize_delegated_credential_signdata(ptls_buffer_t *output, ptls_iovec_t cert, ptls_delegated_credential_t *cred)
{
size_t i;
int ret;

for (i = 0; i < 64; ++i)
ptls_buffer_push(output, ' ');
const char *context_string = "TLS, server delegated credentials";
ptls_buffer_pushv(output, context_string, strlen(context_string));
ptls_buffer_push16(output, cred->protocol_version);
ptls_buffer_pushv(output, cert.base, cert.len);
ptls_buffer_push16(output, cred->signature_scheme);
if ((ret = serialize_delegated_credential_params(output, cred->valid_time, cred->public_key)) != 0)
goto Exit;

ret = 0;
Exit:
return ret;
}

int ptls_sign_delegated_credential(ptls_sign_certificate_t *self, ptls_buffer_t *output, ptls_delegated_credential_t *input, ptls_iovec_t signer_cert)
{
ptls_buffer_t signdata;
int ret;

ptls_buffer_init(&signdata, "", 0);

/* sign context */
if ((ret = serialize_delegated_credential_signdata(&signdata, signer_cert, input)) != 0)
goto Exit;

/* sign */
if ((ret = serialize_delegated_credential_params(output, input->valid_time, input->public_key)) != 0)
goto Exit;
ptls_buffer_push16(output, input->signature_scheme);
ptls_buffer_push_block(output, 2, {
uint16_t dummy;
ret = self->cb(self, NULL, &dummy, output, ptls_iovec_init(signdata.base, signdata.off), &input->signature_scheme, 1);
});

Exit:
ptls_buffer_dispose(&signdata);
return ret;
}

int ptls_verify_delegated_credential(int (*verify_sign)(void *verify_ctx, ptls_iovec_t data, ptls_iovec_t sign), void *verify_ctx,
ptls_delegated_credential_t *cred, ptls_iovec_t signer_cert)
{
ptls_buffer_t signdata;
int ret;

ptls_buffer_init(&signdata, "", 0);

if ((ret = serialize_delegated_credential_signdata(&signdata, signer_cert, cred)) != 0)
goto Exit;
if ((ret = verify_sign(verify_ctx, ptls_iovec_init(signdata.base, signdata.off), cred->signature)) != 0)
return ret;
verify_sign = NULL;

Exit:
if (verify_sign != NULL)
verify_sign(verify_ctx, ptls_iovec_init(NULL, 0), ptls_iovec_init(NULL, 0));
ptls_buffer_dispose(&signdata);
return ret;
}

static void clear_memory(void *p, size_t len)
{
if (len != 0)
Expand Down
Loading