| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007 |
- /*
- * MbedTLS SSL context deserializer from base64 code
- *
- * Copyright The Mbed TLS Contributors
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define MBEDTLS_ALLOW_PRIVATE_ACCESS
- #include "mbedtls/build_info.h"
- #include "mbedtls/debug.h"
- #include <stdio.h>
- #include <stdlib.h>
- #if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
- !defined(MBEDTLS_SSL_TLS_C)
- int main(void)
- {
- printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
- "MBEDTLS_SSL_TLS_C not defined.\n");
- return 0;
- }
- #else
- #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
- #define _CRT_SECURE_NO_DEPRECATE 1
- #endif
- #include <stdint.h>
- #include <stdarg.h>
- #include <string.h>
- #if defined(MBEDTLS_HAVE_TIME)
- #include <time.h>
- #endif
- #include "mbedtls/ssl.h"
- #include "mbedtls/error.h"
- #include "mbedtls/base64.h"
- #include "mbedtls/md.h"
- #include "mbedtls/x509_crt.h"
- #include "mbedtls/ssl_ciphersuites.h"
- /*
- * This program version
- */
- #define PROG_NAME "ssl_context_info"
- #define VER_MAJOR 0
- #define VER_MINOR 1
- /*
- * Flags copied from the Mbed TLS library.
- */
- #define SESSION_CONFIG_TIME_BIT (1 << 0)
- #define SESSION_CONFIG_CRT_BIT (1 << 1)
- #define SESSION_CONFIG_CLIENT_TICKET_BIT (1 << 2)
- #define SESSION_CONFIG_MFL_BIT (1 << 3)
- #define SESSION_CONFIG_TRUNC_HMAC_BIT (1 << 4)
- #define SESSION_CONFIG_ETM_BIT (1 << 5)
- #define SESSION_CONFIG_TICKET_BIT (1 << 6)
- #define CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT (1 << 0)
- #define CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT (1 << 1)
- #define CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT (1 << 2)
- #define CONTEXT_CONFIG_ALPN_BIT (1 << 3)
- #define TRANSFORM_RANDBYTE_LEN 64
- /*
- * Minimum and maximum number of bytes for specific data: context, sessions,
- * certificates, tickets and buffers in the program. The context and session
- * size values have been calculated based on the 'print_deserialized_ssl_context()'
- * and 'print_deserialized_ssl_session()' content.
- */
- #define MIN_CONTEXT_LEN 84
- #define MIN_SESSION_LEN 88
- #define MAX_CONTEXT_LEN 875 /* without session data */
- #define MAX_SESSION_LEN 109 /* without certificate and ticket data */
- #define MAX_CERTIFICATE_LEN ((1 << 24) - 1)
- #define MAX_TICKET_LEN ((1 << 24) - 1)
- #define MIN_SERIALIZED_DATA (MIN_CONTEXT_LEN + MIN_SESSION_LEN)
- #define MAX_SERIALIZED_DATA (MAX_CONTEXT_LEN + MAX_SESSION_LEN + \
- MAX_CERTIFICATE_LEN + MAX_TICKET_LEN)
- #define MIN_BASE64_LEN (MIN_SERIALIZED_DATA * 4 / 3)
- #define MAX_BASE64_LEN (MAX_SERIALIZED_DATA * 4 / 3 + 3)
- /*
- * A macro that prevents from reading out of the ssl buffer range.
- */
- #define CHECK_SSL_END(LEN) \
- do \
- { \
- if (end - ssl < (int) (LEN)) \
- { \
- printf_err("%s", buf_ln_err); \
- return; \
- } \
- } while (0)
- /*
- * Global values
- */
- FILE *b64_file = NULL; /* file with base64 codes to deserialize */
- char conf_keep_peer_certificate = 1; /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE from mbedTLS configuration */
- char conf_dtls_proto = 1; /* MBEDTLS_SSL_PROTO_DTLS from mbedTLS configuration */
- char debug = 0; /* flag for debug messages */
- const char alloc_err[] = "Cannot allocate memory\n";
- const char buf_ln_err[] = "Buffer does not have enough data to complete the parsing\n";
- /*
- * Basic printing functions
- */
- void print_version()
- {
- printf("%s v%d.%d\n", PROG_NAME, VER_MAJOR, VER_MINOR);
- }
- void print_usage()
- {
- print_version();
- printf("\nThis program is used to deserialize an Mbed TLS SSL session from the base64 code provided\n"
- "in the text file. The program can deserialize many codes from one file, but they must be\n"
- "separated, e.g. by a newline.\n\n");
- printf(
- "Usage:\n"
- "\t-f path - Path to the file with base64 code\n"
- "\t-v - Show version\n"
- "\t-h - Show this usage\n"
- "\t-d - Print more information\n"
- "\t--keep-peer-cert=0 - Use this option if you know that the Mbed TLS library\n"
- "\t has been compiled with the MBEDTLS_SSL_KEEP_PEER_CERTIFICATE\n"
- "\t flag. You can also use it if there are some problems with reading\n"
- "\t the information about certificate\n"
- "\t--dtls-protocol=0 - Use this option if you know that the Mbed TLS library\n"
- "\t has been compiled without the MBEDTLS_SSL_PROTO_DTLS flag\n"
- "\n"
- );
- }
- void printf_dbg(const char *str, ...)
- {
- if (debug) {
- va_list args;
- va_start(args, str);
- printf("debug: ");
- vprintf(str, args);
- fflush(stdout);
- va_end(args);
- }
- }
- MBEDTLS_PRINTF_ATTRIBUTE(1, 2)
- void printf_err(const char *str, ...)
- {
- va_list args;
- va_start(args, str);
- fflush(stdout);
- fprintf(stderr, "ERROR: ");
- vfprintf(stderr, str, args);
- fflush(stderr);
- va_end(args);
- }
- /*
- * Exit from the program in case of error
- */
- void error_exit()
- {
- if (NULL != b64_file) {
- fclose(b64_file);
- }
- exit(-1);
- }
- /*
- * This function takes the input arguments of this program
- */
- void parse_arguments(int argc, char *argv[])
- {
- int i = 1;
- if (argc < 2) {
- print_usage();
- error_exit();
- }
- while (i < argc) {
- if (strcmp(argv[i], "-d") == 0) {
- debug = 1;
- } else if (strcmp(argv[i], "-h") == 0) {
- print_usage();
- } else if (strcmp(argv[i], "-v") == 0) {
- print_version();
- } else if (strcmp(argv[i], "-f") == 0) {
- if (++i >= argc) {
- printf_err("File path is empty\n");
- error_exit();
- }
- if (NULL != b64_file) {
- printf_err("Cannot specify more than one file with -f\n");
- error_exit();
- }
- if ((b64_file = fopen(argv[i], "r")) == NULL) {
- printf_err("Cannot find file \"%s\"\n", argv[i]);
- error_exit();
- }
- } else if (strcmp(argv[i], "--keep-peer-cert=0") == 0) {
- conf_keep_peer_certificate = 0;
- } else if (strcmp(argv[i], "--dtls-protocol=0") == 0) {
- conf_dtls_proto = 0;
- } else {
- print_usage();
- error_exit();
- }
- i++;
- }
- }
- /*
- * This function prints base64 code to the stdout
- */
- void print_b64(const uint8_t *b, size_t len)
- {
- size_t i = 0;
- const uint8_t *end = b + len;
- printf("\t");
- while (b < end) {
- if (++i > 75) {
- printf("\n\t");
- i = 0;
- }
- printf("%c", *b++);
- }
- printf("\n");
- fflush(stdout);
- }
- /*
- * This function prints hex code from the buffer to the stdout.
- *
- * /p b buffer with data to print
- * /p len number of bytes to print
- * /p in_line number of bytes in one line
- * /p prefix prefix for the new lines
- */
- void print_hex(const uint8_t *b, size_t len,
- const size_t in_line, const char *prefix)
- {
- size_t i = 0;
- const uint8_t *end = b + len;
- if (prefix == NULL) {
- prefix = "";
- }
- while (b < end) {
- if (++i > in_line) {
- printf("\n%s", prefix);
- i = 1;
- }
- printf("%02X ", (uint8_t) *b++);
- }
- printf("\n");
- fflush(stdout);
- }
- /*
- * Print the value of time_t in format e.g. 2020-01-23 13:05:59
- */
- void print_time(const uint64_t *time)
- {
- #if defined(MBEDTLS_HAVE_TIME)
- char buf[20];
- struct tm *t = gmtime((time_t *) time);
- static const char format[] = "%Y-%m-%d %H:%M:%S";
- if (NULL != t) {
- strftime(buf, sizeof(buf), format, t);
- printf("%s\n", buf);
- } else {
- printf("unknown\n");
- }
- #else
- (void) time;
- printf("not supported\n");
- #endif
- }
- /*
- * Print the input string if the bit is set in the value
- */
- void print_if_bit(const char *str, int bit, int val)
- {
- if (bit & val) {
- printf("\t%s\n", str);
- }
- }
- /*
- * Return pointer to hardcoded "enabled" or "disabled" depending on the input value
- */
- const char *get_enabled_str(int is_en)
- {
- return (is_en) ? "enabled" : "disabled";
- }
- /*
- * Return pointer to hardcoded MFL string value depending on the MFL code at the input
- */
- const char *get_mfl_str(int mfl_code)
- {
- switch (mfl_code) {
- case MBEDTLS_SSL_MAX_FRAG_LEN_NONE:
- return "none";
- case MBEDTLS_SSL_MAX_FRAG_LEN_512:
- return "512";
- case MBEDTLS_SSL_MAX_FRAG_LEN_1024:
- return "1024";
- case MBEDTLS_SSL_MAX_FRAG_LEN_2048:
- return "2048";
- case MBEDTLS_SSL_MAX_FRAG_LEN_4096:
- return "4096";
- default:
- return "error";
- }
- }
- /*
- * Read next base64 code from the 'b64_file'. The 'b64_file' must be opened
- * previously. After each call to this function, the internal file position
- * indicator of the global b64_file is advanced.
- *
- * Note - This function checks the size of the input buffer and if necessary,
- * increases it to the maximum MAX_BASE64_LEN
- *
- * /p b64 pointer to the pointer of the buffer for input data
- * /p max_len pointer to the current buffer capacity. It can be changed if
- * the buffer needs to be increased
- *
- * \retval number of bytes written in to the b64 buffer or 0 in case no more
- * data was found
- */
- size_t read_next_b64_code(uint8_t **b64, size_t *max_len)
- {
- int valid_balance = 0; /* balance between valid and invalid characters */
- size_t len = 0;
- char pad = 0;
- int c = 0;
- while (EOF != c) {
- char c_valid = 0;
- c = fgetc(b64_file);
- if (pad > 0) {
- if (c == '=' && pad == 1) {
- c_valid = 1;
- pad = 2;
- }
- } else if ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '+' || c == '/') {
- c_valid = 1;
- } else if (c == '=') {
- c_valid = 1;
- pad = 1;
- } else if (c == '-') {
- c = '+';
- c_valid = 1;
- } else if (c == '_') {
- c = '/';
- c_valid = 1;
- }
- if (c_valid) {
- /* A string of characters that could be a base64 code. */
- valid_balance++;
- if (len < *max_len) {
- (*b64)[len++] = c;
- } else if (*max_len < MAX_BASE64_LEN) {
- /* Current buffer is too small, but can be resized. */
- void *ptr;
- size_t new_size = (MAX_BASE64_LEN - 4096 > *max_len) ?
- *max_len + 4096 : MAX_BASE64_LEN;
- ptr = realloc(*b64, new_size);
- if (NULL == ptr) {
- printf_err(alloc_err);
- return 0;
- }
- *b64 = ptr;
- *max_len = new_size;
- (*b64)[len++] = c;
- } else {
- /* Too much data so it will be treated as invalid */
- len++;
- }
- } else if (len > 0) {
- /* End of a string that could be a base64 code, but need to check
- * that the length of the characters is correct. */
- valid_balance--;
- if (len < MIN_CONTEXT_LEN) {
- printf_dbg("The code found is too small to be a SSL context.\n");
- len = pad = 0;
- } else if (len > *max_len) {
- printf_err("The code found is too large by %" MBEDTLS_PRINTF_SIZET " bytes.\n",
- len - *max_len);
- len = pad = 0;
- } else if (len % 4 != 0) {
- printf_err("The length of the base64 code found should be a multiple of 4.\n");
- len = pad = 0;
- } else {
- /* Base64 code with valid character length. */
- return len;
- }
- } else {
- valid_balance--;
- }
- /* Detection of potentially wrong file format like: binary, zip, ISO, etc. */
- if (valid_balance < -100) {
- printf_err("Too many bad symbols detected. File check aborted.\n");
- return 0;
- }
- }
- printf_dbg("End of file\n");
- return 0;
- }
- #if !defined(MBEDTLS_X509_REMOVE_INFO)
- /*
- * This function deserializes and prints to the stdout all obtained information
- * about the certificates from provided data.
- *
- * /p ssl pointer to serialized certificate
- * /p len number of bytes in the buffer
- */
- void print_deserialized_ssl_cert(const uint8_t *ssl, uint32_t len)
- {
- enum { STRLEN = 4096 };
- mbedtls_x509_crt crt;
- int ret;
- char str[STRLEN];
- printf("\nCertificate:\n");
- mbedtls_x509_crt_init(&crt);
- ret = mbedtls_x509_crt_parse_der(&crt, ssl, len);
- if (0 != ret) {
- mbedtls_strerror(ret, str, STRLEN);
- printf_err("Invalid format of X.509 - %s\n", str);
- printf("Cannot deserialize:\n\t");
- print_hex(ssl, len, 25, "\t");
- } else {
- mbedtls_x509_crt *current = &crt;
- while (current != NULL) {
- ret = mbedtls_x509_crt_info(str, STRLEN, "\t", current);
- if (0 > ret) {
- mbedtls_strerror(ret, str, STRLEN);
- printf_err("Cannot write to the output - %s\n", str);
- } else {
- printf("%s", str);
- }
- current = current->next;
- if (current) {
- printf("\n");
- }
- }
- }
- mbedtls_x509_crt_free(&crt);
- }
- #endif /* !MBEDTLS_X509_REMOVE_INFO */
- /*
- * This function deserializes and prints to the stdout all obtained information
- * about the session from provided data. This function was built based on
- * mbedtls_ssl_session_load(). mbedtls_ssl_session_load() could not be used
- * due to dependencies on the mbedTLS configuration.
- *
- * The data structure in the buffer:
- * uint64 start_time;
- * uint8 ciphersuite[2]; // defined by the standard
- * uint8 compression; // 0 or 1
- * uint8 session_id_len; // at most 32
- * opaque session_id[32];
- * opaque master[48]; // fixed length in the standard
- * uint32 verify_result;
- * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
- * opaque ticket<0..2^24-1>; // length 0 means no ticket
- * uint32 ticket_lifetime;
- * uint8 mfl_code; // up to 255 according to standard
- * uint8 trunc_hmac; // 0 or 1
- * uint8 encrypt_then_mac; // 0 or 1
- *
- * /p ssl pointer to serialized session
- * /p len number of bytes in the buffer
- * /p session_cfg_flag session configuration flags
- */
- void print_deserialized_ssl_session(const uint8_t *ssl, uint32_t len,
- int session_cfg_flag)
- {
- const struct mbedtls_ssl_ciphersuite_t *ciphersuite_info;
- int ciphersuite_id;
- uint32_t cert_len, ticket_len;
- uint32_t verify_result, ticket_lifetime;
- const uint8_t *end = ssl + len;
- printf("\nSession info:\n");
- if (session_cfg_flag & SESSION_CONFIG_TIME_BIT) {
- uint64_t start;
- CHECK_SSL_END(8);
- start = ((uint64_t) ssl[0] << 56) |
- ((uint64_t) ssl[1] << 48) |
- ((uint64_t) ssl[2] << 40) |
- ((uint64_t) ssl[3] << 32) |
- ((uint64_t) ssl[4] << 24) |
- ((uint64_t) ssl[5] << 16) |
- ((uint64_t) ssl[6] << 8) |
- ((uint64_t) ssl[7]);
- ssl += 8;
- printf("\tstart time : ");
- print_time(&start);
- }
- CHECK_SSL_END(2);
- ciphersuite_id = ((int) ssl[0] << 8) | (int) ssl[1];
- printf_dbg("Ciphersuite ID: %d\n", ciphersuite_id);
- ssl += 2;
- ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
- if (ciphersuite_info == NULL) {
- printf_err("Cannot find ciphersuite info\n");
- } else {
- const mbedtls_cipher_info_t *cipher_info;
- #if defined(MBEDTLS_MD_C)
- const mbedtls_md_info_t *md_info;
- #endif
- printf("\tciphersuite : %s\n", ciphersuite_info->name);
- printf("\tcipher flags : 0x%02X\n", ciphersuite_info->flags);
- cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
- if (cipher_info == NULL) {
- printf_err("Cannot find cipher info\n");
- } else {
- printf("\tcipher : %s\n", cipher_info->name);
- }
- #if defined(MBEDTLS_MD_C)
- md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
- if (md_info == NULL) {
- printf_err("Cannot find Message-Digest info\n");
- } else {
- printf("\tMessage-Digest : %s\n", mbedtls_md_get_name(md_info));
- }
- #endif /* MBEDTLS_MD_C */
- }
- CHECK_SSL_END(1);
- printf("\tcompression : %s\n", get_enabled_str(*ssl++));
- /* Note - Here we can get session ID length from serialized data, but we
- * use hardcoded 32-bytes length. This approach was taken from
- * 'mbedtls_ssl_session_load()'. */
- CHECK_SSL_END(1 + 32);
- printf_dbg("Session id length: %u\n", (uint32_t) *ssl++);
- printf("\tsession ID : ");
- print_hex(ssl, 32, 16, "\t ");
- ssl += 32;
- printf("\tmaster secret : ");
- CHECK_SSL_END(48);
- print_hex(ssl, 48, 16, "\t ");
- ssl += 48;
- CHECK_SSL_END(4);
- verify_result = ((uint32_t) ssl[0] << 24) |
- ((uint32_t) ssl[1] << 16) |
- ((uint32_t) ssl[2] << 8) |
- ((uint32_t) ssl[3]);
- ssl += 4;
- printf("\tverify result : 0x%08X\n", verify_result);
- if (SESSION_CONFIG_CRT_BIT & session_cfg_flag) {
- if (conf_keep_peer_certificate) {
- CHECK_SSL_END(3);
- cert_len = ((uint32_t) ssl[0] << 16) |
- ((uint32_t) ssl[1] << 8) |
- ((uint32_t) ssl[2]);
- ssl += 3;
- printf_dbg("Certificate length: %u\n", cert_len);
- if (cert_len > 0) {
- CHECK_SSL_END(cert_len);
- #if !defined(MBEDTLS_X509_REMOVE_INFO)
- print_deserialized_ssl_cert(ssl, cert_len);
- #endif
- ssl += cert_len;
- }
- } else {
- printf("\tPeer digest : ");
- CHECK_SSL_END(1);
- switch ((mbedtls_md_type_t) *ssl++) {
- case MBEDTLS_MD_NONE:
- printf("none\n");
- break;
- case MBEDTLS_MD_MD5:
- printf("MD5\n");
- break;
- case MBEDTLS_MD_SHA1:
- printf("SHA1\n");
- break;
- case MBEDTLS_MD_SHA224:
- printf("SHA224\n");
- break;
- case MBEDTLS_MD_SHA256:
- printf("SHA256\n");
- break;
- case MBEDTLS_MD_SHA384:
- printf("SHA384\n");
- break;
- case MBEDTLS_MD_SHA512:
- printf("SHA512\n");
- break;
- case MBEDTLS_MD_RIPEMD160:
- printf("RIPEMD160\n");
- break;
- default:
- printf("undefined or erroneous\n");
- break;
- }
- CHECK_SSL_END(1);
- cert_len = (uint32_t) *ssl++;
- printf_dbg("Message-Digest length: %u\n", cert_len);
- if (cert_len > 0) {
- printf("\tPeer digest cert : ");
- CHECK_SSL_END(cert_len);
- print_hex(ssl, cert_len, 16, "\t ");
- ssl += cert_len;
- }
- }
- }
- if (SESSION_CONFIG_CLIENT_TICKET_BIT & session_cfg_flag) {
- printf("\nTicket:\n");
- CHECK_SSL_END(3);
- ticket_len = ((uint32_t) ssl[0] << 16) |
- ((uint32_t) ssl[1] << 8) |
- ((uint32_t) ssl[2]);
- ssl += 3;
- printf_dbg("Ticket length: %u\n", ticket_len);
- if (ticket_len > 0) {
- printf("\t");
- CHECK_SSL_END(ticket_len);
- print_hex(ssl, ticket_len, 22, "\t");
- ssl += ticket_len;
- printf("\n");
- }
- CHECK_SSL_END(4);
- ticket_lifetime = ((uint32_t) ssl[0] << 24) |
- ((uint32_t) ssl[1] << 16) |
- ((uint32_t) ssl[2] << 8) |
- ((uint32_t) ssl[3]);
- ssl += 4;
- printf("\tlifetime : %u sec.\n", ticket_lifetime);
- }
- if (ssl < end) {
- printf("\nSession others:\n");
- }
- if (SESSION_CONFIG_MFL_BIT & session_cfg_flag) {
- CHECK_SSL_END(1);
- printf("\tMFL : %s\n", get_mfl_str(*ssl++));
- }
- if (SESSION_CONFIG_TRUNC_HMAC_BIT & session_cfg_flag) {
- CHECK_SSL_END(1);
- printf("\tnegotiate truncated HMAC : %s\n", get_enabled_str(*ssl++));
- }
- if (SESSION_CONFIG_ETM_BIT & session_cfg_flag) {
- CHECK_SSL_END(1);
- printf("\tEncrypt-then-MAC : %s\n", get_enabled_str(*ssl++));
- }
- if (0 != (end - ssl)) {
- printf_err("%i bytes left to analyze from session\n", (int32_t) (end - ssl));
- }
- }
- /*
- * This function deserializes and prints to the stdout all obtained information
- * about the context from provided data. This function was built based on
- * mbedtls_ssl_context_load(). mbedtls_ssl_context_load() could not be used
- * due to dependencies on the mbedTLS configuration and the configuration of
- * the context when serialization was created.
- *
- * The data structure in the buffer:
- * // header
- * uint8 version[3];
- * uint8 configuration[5];
- * // session sub-structure
- * uint32_t session_len;
- * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save()
- * // transform sub-structure
- * uint8 random[64]; // ServerHello.random+ClientHello.random
- * uint8 in_cid_len;
- * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value
- * uint8 out_cid_len;
- * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use
- * // fields from ssl_context
- * uint32 badmac_seen; // DTLS: number of records with failing MAC
- * uint64 in_window_top; // DTLS: last validated record seq_num
- * uint64 in_window; // DTLS: bitmask for replay protection
- * uint8 disable_datagram_packing; // DTLS: only one record per datagram
- * uint64 cur_out_ctr; // Record layer: outgoing sequence number
- * uint16 mtu; // DTLS: path mtu (max outgoing fragment size)
- * uint8 alpn_chosen_len;
- * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
- *
- * /p ssl pointer to serialized session
- * /p len number of bytes in the buffer
- */
- void print_deserialized_ssl_context(const uint8_t *ssl, size_t len)
- {
- const uint8_t *end = ssl + len;
- uint32_t session_len;
- int session_cfg_flag;
- int context_cfg_flag;
- printf("\nMbed TLS version:\n");
- CHECK_SSL_END(3 + 2 + 3);
- printf("\tmajor %u\n", (uint32_t) *ssl++);
- printf("\tminor %u\n", (uint32_t) *ssl++);
- printf("\tpath %u\n", (uint32_t) *ssl++);
- printf("\nEnabled session and context configuration:\n");
- session_cfg_flag = ((int) ssl[0] << 8) | ((int) ssl[1]);
- ssl += 2;
- context_cfg_flag = ((int) ssl[0] << 16) |
- ((int) ssl[1] << 8) |
- ((int) ssl[2]);
- ssl += 3;
- printf_dbg("Session config flags 0x%04X\n", session_cfg_flag);
- printf_dbg("Context config flags 0x%06X\n", context_cfg_flag);
- print_if_bit("MBEDTLS_HAVE_TIME", SESSION_CONFIG_TIME_BIT, session_cfg_flag);
- print_if_bit("MBEDTLS_X509_CRT_PARSE_C", SESSION_CONFIG_CRT_BIT, session_cfg_flag);
- print_if_bit("MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", SESSION_CONFIG_MFL_BIT, session_cfg_flag);
- print_if_bit("MBEDTLS_SSL_ENCRYPT_THEN_MAC", SESSION_CONFIG_ETM_BIT, session_cfg_flag);
- print_if_bit("MBEDTLS_SSL_SESSION_TICKETS", SESSION_CONFIG_TICKET_BIT, session_cfg_flag);
- print_if_bit("MBEDTLS_SSL_SESSION_TICKETS and client",
- SESSION_CONFIG_CLIENT_TICKET_BIT,
- session_cfg_flag);
- print_if_bit("MBEDTLS_SSL_DTLS_CONNECTION_ID",
- CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT,
- context_cfg_flag);
- print_if_bit("MBEDTLS_SSL_DTLS_ANTI_REPLAY",
- CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT,
- context_cfg_flag);
- print_if_bit("MBEDTLS_SSL_ALPN", CONTEXT_CONFIG_ALPN_BIT, context_cfg_flag);
- CHECK_SSL_END(4);
- session_len = ((uint32_t) ssl[0] << 24) |
- ((uint32_t) ssl[1] << 16) |
- ((uint32_t) ssl[2] << 8) |
- ((uint32_t) ssl[3]);
- ssl += 4;
- printf_dbg("Session length %u\n", session_len);
- CHECK_SSL_END(session_len);
- print_deserialized_ssl_session(ssl, session_len, session_cfg_flag);
- ssl += session_len;
- printf("\nRandom bytes:\n\t");
- CHECK_SSL_END(TRANSFORM_RANDBYTE_LEN);
- print_hex(ssl, TRANSFORM_RANDBYTE_LEN, 22, "\t");
- ssl += TRANSFORM_RANDBYTE_LEN;
- printf("\nContext others:\n");
- if (CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT & context_cfg_flag) {
- uint8_t cid_len;
- CHECK_SSL_END(1);
- cid_len = *ssl++;
- printf_dbg("In CID length %u\n", (uint32_t) cid_len);
- printf("\tin CID : ");
- if (cid_len > 0) {
- CHECK_SSL_END(cid_len);
- print_hex(ssl, cid_len, 20, "\t");
- ssl += cid_len;
- } else {
- printf("none\n");
- }
- CHECK_SSL_END(1);
- cid_len = *ssl++;
- printf_dbg("Out CID length %u\n", (uint32_t) cid_len);
- printf("\tout CID : ");
- if (cid_len > 0) {
- CHECK_SSL_END(cid_len);
- print_hex(ssl, cid_len, 20, "\t");
- ssl += cid_len;
- } else {
- printf("none\n");
- }
- }
- if (CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT & context_cfg_flag) {
- uint32_t badmac_seen;
- CHECK_SSL_END(4);
- badmac_seen = ((uint32_t) ssl[0] << 24) |
- ((uint32_t) ssl[1] << 16) |
- ((uint32_t) ssl[2] << 8) |
- ((uint32_t) ssl[3]);
- ssl += 4;
- printf("\tbad MAC seen number : %u\n", badmac_seen);
- /* value 'in_window_top' from mbedtls_ssl_context */
- printf("\tlast validated record sequence no. : ");
- CHECK_SSL_END(8);
- print_hex(ssl, 8, 20, "");
- ssl += 8;
- /* value 'in_window' from mbedtls_ssl_context */
- printf("\tbitmask for replay detection : ");
- CHECK_SSL_END(8);
- print_hex(ssl, 8, 20, "");
- ssl += 8;
- }
- if (conf_dtls_proto) {
- CHECK_SSL_END(1);
- printf("\tDTLS datagram packing : %s\n",
- get_enabled_str(!(*ssl++)));
- }
- /* value 'cur_out_ctr' from mbedtls_ssl_context */
- printf("\toutgoing record sequence no. : ");
- CHECK_SSL_END(8);
- print_hex(ssl, 8, 20, "");
- ssl += 8;
- if (conf_dtls_proto) {
- uint16_t mtu;
- CHECK_SSL_END(2);
- mtu = (ssl[0] << 8) | ssl[1];
- ssl += 2;
- printf("\tMTU : %u\n", mtu);
- }
- if (CONTEXT_CONFIG_ALPN_BIT & context_cfg_flag) {
- uint8_t alpn_len;
- CHECK_SSL_END(1);
- alpn_len = *ssl++;
- printf_dbg("ALPN length %u\n", (uint32_t) alpn_len);
- printf("\tALPN negotiation : ");
- CHECK_SSL_END(alpn_len);
- if (alpn_len > 0) {
- if (strlen((const char *) ssl) == alpn_len) {
- printf("%s\n", ssl);
- } else {
- printf("\n");
- printf_err("\tALPN negotiation is incorrect\n");
- }
- ssl += alpn_len;
- } else {
- printf("not selected\n");
- }
- }
- if (0 != (end - ssl)) {
- printf_err("%i bytes left to analyze from context\n", (int32_t) (end - ssl));
- }
- printf("\n");
- }
- int main(int argc, char *argv[])
- {
- enum { SSL_INIT_LEN = 4096 };
- uint32_t b64_counter = 0;
- uint8_t *b64_buf = NULL;
- uint8_t *ssl_buf = NULL;
- size_t b64_max_len = SSL_INIT_LEN;
- size_t ssl_max_len = SSL_INIT_LEN;
- size_t ssl_len = 0;
- /* The 'b64_file' is opened when parsing arguments to check that the
- * file name is correct */
- parse_arguments(argc, argv);
- if (NULL != b64_file) {
- b64_buf = malloc(SSL_INIT_LEN);
- ssl_buf = malloc(SSL_INIT_LEN);
- if (NULL == b64_buf || NULL == ssl_buf) {
- printf_err(alloc_err);
- fclose(b64_file);
- b64_file = NULL;
- }
- }
- while (NULL != b64_file) {
- size_t b64_len = read_next_b64_code(&b64_buf, &b64_max_len);
- if (b64_len > 0) {
- int ret;
- size_t ssl_required_len = b64_len * 3 / 4 + 1;
- /* Allocate more memory if necessary. */
- if (ssl_required_len > ssl_max_len) {
- void *ptr = realloc(ssl_buf, ssl_required_len);
- if (NULL == ptr) {
- printf_err(alloc_err);
- fclose(b64_file);
- b64_file = NULL;
- break;
- }
- ssl_buf = ptr;
- ssl_max_len = ssl_required_len;
- }
- printf("\nDeserializing number %u:\n", ++b64_counter);
- printf("\nBase64 code:\n");
- print_b64(b64_buf, b64_len);
- ret = mbedtls_base64_decode(ssl_buf, ssl_max_len, &ssl_len, b64_buf, b64_len);
- if (ret != 0) {
- mbedtls_strerror(ret, (char *) b64_buf, b64_max_len);
- printf_err("base64 code cannot be decoded - %s\n", b64_buf);
- continue;
- }
- if (debug) {
- printf("\nDecoded data in hex:\n\t");
- print_hex(ssl_buf, ssl_len, 25, "\t");
- }
- print_deserialized_ssl_context(ssl_buf, ssl_len);
- } else {
- fclose(b64_file);
- b64_file = NULL;
- }
- }
- free(b64_buf);
- free(ssl_buf);
- if (b64_counter > 0) {
- printf_dbg("Finished. Found %u base64 codes\n", b64_counter);
- } else {
- printf("Finished. No valid base64 code found\n");
- }
- return 0;
- }
- #endif /* MBEDTLS_X509_CRT_PARSE_C */
|