From f8ca3ea1dad033ddb0276a91a3684ff96d80d3a8 Mon Sep 17 00:00:00 2001 From: mkardous-silabs <84793247+mkardous-silabs@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:34:13 -0400 Subject: [PATCH 01/11] Add mld6 source file to fix missing include (#214) * clean up * Add mld6 source file with include fix * Restyle Add mld6 source file to fix missing include (#215) * Restyled by whitespace * Restyled by clang-format * Restyled by prettier-markdown --------- Co-authored-by: Restyled.io --------- Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com> Co-authored-by: Restyled.io --- src/core/ipv6/mld6.c | 638 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 638 insertions(+) create mode 100644 src/core/ipv6/mld6.c diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c new file mode 100644 index 0000000000..091c5ad3b1 --- /dev/null +++ b/src/core/ipv6/mld6.c @@ -0,0 +1,638 @@ +/** + * @file + * Multicast listener discovery + * + * @defgroup mld6 MLD6 + * @ingroup ip6 + * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. + * No support for MLDv2.\n + * Note: The allnodes (ff01::1, ff02::1) group is assumed be received by your + * netif since it must always be received for correct IPv6 operation (e.g. + * SLAAC). Ensure the netif filters are configured accordingly!\n The netif + * flags also need NETIF_FLAG_MLD6 flag set to enable MLD6 on a netif + * ("netif->flags |= NETIF_FLAG_MLD6;").\n To be called from TCPIP thread. + */ + +/* + * Copyright (c) 2010 Inico Technologies Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Ivan Delamer + * + * + * Please coordinate changes and requests with Ivan Delamer + * + */ + +/* Based on igmp.c implementation of igmp v2 protocol */ + +#include "lwip/opt.h" + +#if LWIP_IPV6 && \ + LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ + +#include "lwip/icmp6.h" +#include "lwip/inet_chksum.h" +#include "lwip/ip.h" +#include "lwip/ip6.h" +#include "lwip/ip6_addr.h" +#include "lwip/memp.h" +#include "lwip/mld6.h" +#include "lwip/netif.h" +#include "lwip/pbuf.h" +#include "lwip/prot/mld6.h" +#include "lwip/stats.h" + +#include + +/* + * MLD constants + */ +#define MLD6_HL 1 +#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) + +#define MLD6_GROUP_NON_MEMBER 0 +#define MLD6_GROUP_DELAYING_MEMBER 1 +#define MLD6_GROUP_IDLE_MEMBER 2 + +/* Forward declarations. */ +static struct mld_group *mld6_new_group(struct netif *ifp, + const ip6_addr_t *addr); +static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); +static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); + +#if SL_LWIP_MLD6_TIMERS_ONDEMAND +#include "lwip/timeouts.h" +#include "stdbool.h" +static bool is_tmr_start = false; +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ + +/** + * Stop MLD processing on interface + * + * @param netif network interface on which stop MLD processing + */ +err_t mld6_stop(struct netif *netif) { + struct mld_group *group = netif_mld6_data(netif); + + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); + + while (group != NULL) { + struct mld_group *next = group->next; /* avoid use-after-free below */ + + /* disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, &(group->group_address), + NETIF_DEL_MAC_FILTER); + } + + /* free group */ + memp_free(MEMP_MLD6_GROUP, group); + + /* move to "next" */ + group = next; + } + return ERR_OK; +} + +/** + * Report MLD memberships for this interface + * + * @param netif network interface on which report MLD memberships + */ +void mld6_report_groups(struct netif *netif) { + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + group = group->next; + } +} + +/** + * Search for a group that is joined on a netif + * + * @param ifp the network interface for which to look + * @param addr the group ipv6 address to search for + * @return a struct mld_group* if the group has been found, + * NULL if the group wasn't found. + */ +struct mld_group *mld6_lookfor_group(struct netif *ifp, + const ip6_addr_t *addr) { + struct mld_group *group = netif_mld6_data(ifp); + + while (group != NULL) { + if (ip6_addr_cmp(&(group->group_address), addr)) { + return group; + } + group = group->next; + } + + return NULL; +} + +/** + * create a new group + * + * @param ifp the network interface for which to create + * @param addr the new group ipv6 + * @return a struct mld_group*, + * NULL on memory error. + */ +static struct mld_group *mld6_new_group(struct netif *ifp, + const ip6_addr_t *addr) { + struct mld_group *group; + + group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); + if (group != NULL) { + ip6_addr_set(&(group->group_address), addr); + group->timer = 0; /* Not running */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + group->use = 0; + group->next = netif_mld6_data(ifp); + + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); + } + + return group; +} + +/** + * Remove a group from the mld_group_list, but do not free it yet + * + * @param group the group to remove + * @return ERR_OK if group was removed from the list, an err_t otherwise + */ +static err_t mld6_remove_group(struct netif *netif, struct mld_group *group) { + err_t err = ERR_OK; + + /* Is it the first group? */ + if (netif_mld6_data(netif) == group) { + netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, + group->next); + } else { + /* look for group further down the list */ + struct mld_group *tmpGroup; + for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; + tmpGroup = tmpGroup->next) { + if (tmpGroup->next == group) { + tmpGroup->next = group->next; + break; + } + } + /* Group not find group */ + if (tmpGroup == NULL) { + err = ERR_ARG; + } + } + + return err; +} + +/** + * Process an input MLD message. Called by icmp6_input. + * + * @param p the mld packet, p->payload pointing to the icmpv6 header + * @param inp the netif on which this packet was received + */ +void mld6_input(struct pbuf *p, struct netif *inp) { + struct mld_header *mld_hdr; + struct mld_group *group; + + MLD6_STATS_INC(mld6.recv); + + /* Check that mld header fits in packet. */ + if (p->len < sizeof(struct mld_header)) { + /* @todo debug message */ + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + MLD6_STATS_INC(mld6.drop); + return; + } + + mld_hdr = (struct mld_header *)p->payload; + + switch (mld_hdr->type) { + case ICMP6_TYPE_MLQ: /* Multicast listener query. */ + /* Is it a general query? */ + if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && + ip6_addr_isany(&(mld_hdr->multicast_address))) { + MLD6_STATS_INC(mld6.rx_general); + /* Report all groups, except all nodes group, and if-local groups. */ + group = netif_mld6_data(inp); + while (group != NULL) { + if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && + (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + group = group->next; + } + } else { + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_group); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* Schedule a report. */ + mld6_delayed_report(group, mld_hdr->max_resp_delay); + } + } + break; /* ICMP6_TYPE_MLQ */ + case ICMP6_TYPE_MLR: /* Multicast listener report. */ + /* Have we joined this group? + * We use IP6 destination address to have a memory aligned copy. + * mld_hdr->multicast_address should be the same. */ + MLD6_STATS_INC(mld6.rx_report); + group = mld6_lookfor_group(inp, ip6_current_dest_addr()); + if (group != NULL) { + /* If we are waiting to report, cancel it. */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + group->timer = 0; /* stopped */ + group->group_state = MLD6_GROUP_IDLE_MEMBER; + group->last_reporter_flag = 0; + } + } + break; /* ICMP6_TYPE_MLR */ + case ICMP6_TYPE_MLD: /* Multicast listener done. */ + /* Do nothing, router will query us. */ + break; /* ICMP6_TYPE_MLD */ + default: + MLD6_STATS_INC(mld6.proterr); + MLD6_STATS_INC(mld6.drop); + break; + } + + pbuf_free(p); +} + +/** + * @ingroup mld6 + * Join a group on one or all network interfaces. + * + * If the group is to be joined on all interfaces, the given group address must + * not have a zone set (i.e., it must have its zone index set to IP6_NO_ZONE). + * If the group is to be joined on one particular interface, the given group + * address may or may not have a zone set. + * + * @param srcaddr ipv6 address (zoned) of the network interface which should + * join a new group. If IP6_ADDR_ANY6, join on all netifs + * @param groupaddr the ipv6 address of the group to join (possibly but not + * necessarily zoned) + * @return ERR_OK if group was joined on the netif(s), an err_t otherwise + */ +err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + LWIP_ASSERT_CORE_LOCKED(); + + /* loop through netif's */ + NETIF_FOREACH(netif) { + /* Should we join this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err = mld6_joingroup_netif(netif, groupaddr); + if (err != ERR_OK) { + return err; + } + } + } + + return err; +} + +/** + * @ingroup mld6 + * Join a group on a network interface. + * + * @param netif the network interface which should join a new group. + * @param groupaddr the ipv6 address of the group to join (possibly but not + * necessarily zoned) + * @return ERR_OK if group was joined on the netif, an err_t otherwise + */ +err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) { + struct mld_group *group; +#if LWIP_IPV6_SCOPES + ip6_addr_t ip6addr; + + /* If the address has a particular scope but no zone set, use the netif to + * set one now. Within the mld6 module, all addresses are properly zoned. */ + if (ip6_addr_lacks_zone(groupaddr, IP6_MULTICAST)) { + ip6_addr_set(&ip6addr, groupaddr); + ip6_addr_assign_zone(&ip6addr, IP6_MULTICAST, netif); + groupaddr = &ip6addr; + } + IP6_ADDR_ZONECHECK_NETIF(groupaddr, netif); +#endif /* LWIP_IPV6_SCOPES */ + + LWIP_ASSERT_CORE_LOCKED(); + + /* find group or create a new one if not found */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group == NULL) { + /* Joining a new group. Create a new group entry. */ + group = mld6_new_group(netif, groupaddr); + if (group == NULL) { + return ERR_MEM; + } + + /* Activate this address on the MAC layer. */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); + } + + /* Report our membership. */ + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); + } + + /* Increment group use */ + group->use++; + return ERR_OK; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * Zoning of address follows the same rules as @ref mld6_joingroup. + * + * @param srcaddr ipv6 address (zoned) of the network interface which should + * leave the group. If IP6_ADDR_ANY6, leave on all netifs + * @param groupaddr the ipv6 address of the group to leave (possibly, but not + * necessarily zoned) + * @return ERR_OK if group was left on the netif(s), an err_t otherwise + */ +err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { + err_t err = ERR_VAL; /* no matching interface */ + struct netif *netif; + + LWIP_ASSERT_CORE_LOCKED(); + + /* loop through netif's */ + NETIF_FOREACH(netif) { + /* Should we leave this interface ? */ + if (ip6_addr_isany(srcaddr) || + netif_get_ip6_addr_match(netif, srcaddr) >= 0) { + err_t res = mld6_leavegroup_netif(netif, groupaddr); + if (err != ERR_OK) { + /* Store this result if we have not yet gotten a success */ + err = res; + } + } + } + + return err; +} + +/** + * @ingroup mld6 + * Leave a group on a network interface. + * + * @param netif the network interface which should leave the group. + * @param groupaddr the ipv6 address of the group to leave (possibly, but not + * necessarily zoned) + * @return ERR_OK if group was left on the netif, an err_t otherwise + */ +err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) { + struct mld_group *group; +#if LWIP_IPV6_SCOPES + ip6_addr_t ip6addr; + + if (ip6_addr_lacks_zone(groupaddr, IP6_MULTICAST)) { + ip6_addr_set(&ip6addr, groupaddr); + ip6_addr_assign_zone(&ip6addr, IP6_MULTICAST, netif); + groupaddr = &ip6addr; + } + IP6_ADDR_ZONECHECK_NETIF(groupaddr, netif); +#endif /* LWIP_IPV6_SCOPES */ + + LWIP_ASSERT_CORE_LOCKED(); + + /* find group */ + group = mld6_lookfor_group(netif, groupaddr); + + if (group != NULL) { + /* Leave if there is no other use of the group */ + if (group->use <= 1) { + /* Remove the group from the list */ + mld6_remove_group(netif, group); + + /* If we are the last reporter for this group */ + if (group->last_reporter_flag) { + MLD6_STATS_INC(mld6.tx_leave); + mld6_send(netif, group, ICMP6_TYPE_MLD); + } + + /* Disable the group at the MAC level */ + if (netif->mld_mac_filter != NULL) { + netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); + } + + /* free group struct */ + memp_free(MEMP_MLD6_GROUP, group); + } else { + /* Decrement group use */ + group->use--; + } + + /* Left group */ + return ERR_OK; + } + + /* Group not found */ + return ERR_VAL; +} + +#if SL_LWIP_MLD6_TIMERS_ONDEMAND +static void mld6_timeout_cb(void *arg) { + LWIP_UNUSED_ARG(arg); + + mld6_tmr(); +} +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ +/** + * Periodic timer for mld processing. Must be called every + * MLD6_TMR_INTERVAL milliseconds (100). + * + * When a delaying member expires, a membership report is sent. + */ +void mld6_tmr(void) { + struct netif *netif; +#if SL_LWIP_MLD6_TIMERS_ONDEMAND + bool tmr_restart = false; +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ + + NETIF_FOREACH(netif) { + struct mld_group *group = netif_mld6_data(netif); + + while (group != NULL) { + if (group->timer > 0) { + group->timer--; + if (group->timer == 0) { + /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report + * for this group */ + if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { + MLD6_STATS_INC(mld6.tx_report); + mld6_send(netif, group, ICMP6_TYPE_MLR); + group->group_state = MLD6_GROUP_IDLE_MEMBER; + } + } +#if SL_LWIP_MLD6_TIMERS_ONDEMAND + else { + tmr_restart = true; + } +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ + } + group = group->next; + } + } +#if SL_LWIP_MLD6_TIMERS_ONDEMAND + if (tmr_restart) { + sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); + } else { + sys_untimeout(mld6_timeout_cb, NULL); + is_tmr_start = false; + } +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ +} + +/** + * Schedule a delayed membership report for a group + * + * @param group the mld_group for which "delaying" membership report + * should be sent + * @param maxresp_in the max resp delay provided in the query + */ +static void mld6_delayed_report(struct mld_group *group, u16_t maxresp_in) { + /* Convert maxresp from milliseconds to tmr ticks */ + u16_t maxresp = maxresp_in / MLD6_TMR_INTERVAL; + if (maxresp == 0) { + maxresp = 1; + } + +#ifdef LWIP_RAND + /* Randomize maxresp. (if LWIP_RAND is supported) */ + maxresp = (u16_t)(LWIP_RAND() % maxresp); + if (maxresp == 0) { + maxresp = 1; + } +#endif /* LWIP_RAND */ + + /* Apply timer value if no report has been scheduled already. */ + if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || + ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && + ((group->timer == 0) || (maxresp < group->timer)))) { + group->timer = maxresp; + group->group_state = MLD6_GROUP_DELAYING_MEMBER; +#if SL_LWIP_MLD6_TIMERS_ONDEMAND + if (!is_tmr_start) { + sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); + is_tmr_start = true; + } +#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ + } +} + +/** + * Send a MLD message (report or done). + * + * An IPv6 hop-by-hop options header with a router alert option + * is prepended. + * + * @param group the group to report or quit + * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) + */ +static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type) { + struct mld_header *mld_hdr; + struct pbuf *p; + const ip6_addr_t *src_addr; + + /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ + p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + MLD6_HBH_HLEN, PBUF_RAM); + if (p == NULL) { + MLD6_STATS_INC(mld6.memerr); + return; + } + + /* Move to make room for Hop-by-hop options header. */ + if (pbuf_remove_header(p, MLD6_HBH_HLEN)) { + pbuf_free(p); + MLD6_STATS_INC(mld6.lenerr); + return; + } + + /* Select our source address. */ + if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { + /* This is a special case, when we are performing duplicate address + * detection. We must join the multicast group, but we don't have a valid + * address yet. */ + src_addr = IP6_ADDR_ANY6; + } else { + /* Use link-local address as source address. */ + src_addr = netif_ip6_addr(netif, 0); + } + + /* MLD message header pointer. */ + mld_hdr = (struct mld_header *)p->payload; + + /* Set fields. */ + mld_hdr->type = type; + mld_hdr->code = 0; + mld_hdr->chksum = 0; + mld_hdr->max_resp_delay = 0; + mld_hdr->reserved = 0; + ip6_addr_copy_to_packed(mld_hdr->multicast_address, group->group_address); + +#if CHECKSUM_GEN_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { + mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, + &(group->group_address)); + } +#endif /* CHECKSUM_GEN_ICMP6 */ + + /* Add hop-by-hop headers options: router alert with MLD value. */ + ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + + if (type == ICMP6_TYPE_MLR) { + /* Remember we were the last to report */ + group->last_reporter_flag = 1; + } + + /* Send the packet out. */ + MLD6_STATS_INC(mld6.xmit); + ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, + &(group->group_address), MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); + pbuf_free(p); +} + +#endif /* LWIP_IPV6 */ From 2460c9bb5a51ce0449c9e8aa2fb50dec05c24e45 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous Date: Mon, 29 Jul 2024 15:55:08 -0400 Subject: [PATCH 02/11] WIP --- matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h | 130 + .../tinycrypt/inc/tinycrypt/cbc_mode.h | 151 + .../tinycrypt/inc/tinycrypt/ccm_mode.h | 211 ++ .../tinycrypt/inc/tinycrypt/cmac_mode.h | 194 ++ .../tinycrypt/inc/tinycrypt/constants.h | 61 + .../tinycrypt/inc/tinycrypt/ctr_mode.h | 108 + .../tinycrypt/inc/tinycrypt/ctr_prng.h | 166 + matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h | 1023 ++++--- .../mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h | 266 +- .../mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h | 283 +- .../inc/tinycrypt/ecc_platform_specific.h | 81 + matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h | 139 + .../tinycrypt/inc/tinycrypt/hmac_prng.h | 164 + .../mbedtls/tinycrypt/inc/tinycrypt/sha256.h | 129 + .../mbedtls/tinycrypt/inc/tinycrypt/utils.h | 121 + matter/mbedtls/tinycrypt/src/aes_decrypt.c | 164 + matter/mbedtls/tinycrypt/src/aes_encrypt.c | 191 ++ matter/mbedtls/tinycrypt/src/cbc_mode.c | 114 + matter/mbedtls/tinycrypt/src/ccm_mode.c | 266 ++ matter/mbedtls/tinycrypt/src/cmac_mode.c | 254 ++ matter/mbedtls/tinycrypt/src/ctr_mode.c | 85 + matter/mbedtls/tinycrypt/src/ctr_prng.c | 283 ++ matter/mbedtls/tinycrypt/src/ecc.c | 2680 ++++++----------- matter/mbedtls/tinycrypt/src/ecc_dh.c | 374 +-- matter/mbedtls/tinycrypt/src/ecc_dsa.c | 598 ++-- .../tinycrypt/src/ecc_platform_specific.c | 105 + matter/mbedtls/tinycrypt/src/hmac.c | 147 + matter/mbedtls/tinycrypt/src/hmac_prng.c | 230 ++ matter/mbedtls/tinycrypt/src/sha256.c | 217 ++ matter/mbedtls/tinycrypt/src/utils.c | 74 + 30 files changed, 6024 insertions(+), 2985 deletions(-) create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h create mode 100644 matter/mbedtls/tinycrypt/src/aes_decrypt.c create mode 100644 matter/mbedtls/tinycrypt/src/aes_encrypt.c create mode 100644 matter/mbedtls/tinycrypt/src/cbc_mode.c create mode 100644 matter/mbedtls/tinycrypt/src/ccm_mode.c create mode 100644 matter/mbedtls/tinycrypt/src/cmac_mode.c create mode 100644 matter/mbedtls/tinycrypt/src/ctr_mode.c create mode 100644 matter/mbedtls/tinycrypt/src/ctr_prng.c create mode 100644 matter/mbedtls/tinycrypt/src/ecc_platform_specific.c create mode 100644 matter/mbedtls/tinycrypt/src/hmac.c create mode 100644 matter/mbedtls/tinycrypt/src/hmac_prng.c create mode 100644 matter/mbedtls/tinycrypt/src/sha256.c create mode 100644 matter/mbedtls/tinycrypt/src/utils.c diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h new file mode 100644 index 0000000000..b612213a0e --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h @@ -0,0 +1,130 @@ +/* aes.h - TinyCrypt interface to an AES-128 implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to an AES-128 implementation. + * + * Overview: AES-128 is a NIST approved block cipher specified in + * FIPS 197. Block ciphers are deterministic algorithms that + * perform a transformation specified by a symmetric key in fixed- + * length data sets, also called blocks. + * + * Security: AES-128 provides approximately 128 bits of security. + * + * Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key. + * + * 2) call tc_aes_encrypt/decrypt to process the data. + */ + +#ifndef __TC_AES_H__ +#define __TC_AES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define Nb (4) /* number of columns (32-bit words) comprising the state */ +#define Nk (4) /* number of 32-bit words comprising the key */ +#define Nr (10) /* number of rounds */ +#define TC_AES_BLOCK_SIZE (Nb*Nk) +#define TC_AES_KEY_SIZE (Nb*Nk) + +typedef struct tc_aes_key_sched_struct { + unsigned int words[Nb*(Nr+1)]; +} *TCAesKeySched_t; + +/** + * @brief Set AES-128 encryption key + * Uses key k to initialize s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL + * @note This implementation skips the additional steps required for keys + * larger than 128 bits, and must not be used for AES-192 or + * AES-256 key schedule -- see FIPS 197 for details + * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct + * @param k IN -- points to the AES key + */ +int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k); + +/** + * @brief AES-128 Encryption procedure + * Encrypts contents of in buffer into out buffer under key; + * schedule s + * @note Assumes s was initialized by aes_set_encrypt_key; + * out and in point to 16 byte buffers + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL + * @param out IN/OUT -- buffer to receive ciphertext block + * @param in IN -- a plaintext block to encrypt + * @param s IN -- initialized AES key schedule + */ +int tc_aes_encrypt(uint8_t *out, const uint8_t *in, + const TCAesKeySched_t s); + +/** + * @brief Set the AES-128 decryption key + * Uses key k to initialize s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL + * @note This is the implementation of the straightforward inverse cipher + * using the cipher documented in FIPS-197 figure 12, not the + * equivalent inverse cipher presented in Figure 15 + * @warning This routine skips the additional steps required for keys larger + * than 128, and must not be used for AES-192 or AES-256 key + * schedule -- see FIPS 197 for details + * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct + * @param k IN -- points to the AES key + */ +int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k); + +/** + * @brief AES-128 Encryption procedure + * Decrypts in buffer into out buffer under key schedule s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL + * @note Assumes s was initialized by aes_set_encrypt_key + * out and in point to 16 byte buffers + * @param out IN/OUT -- buffer to receive ciphertext block + * @param in IN -- a plaintext block to encrypt + * @param s IN -- initialized AES key schedule + */ +int tc_aes_decrypt(uint8_t *out, const uint8_t *in, + const TCAesKeySched_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_AES_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h new file mode 100644 index 0000000000..4a837fd01a --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h @@ -0,0 +1,151 @@ +/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CBC mode implementation. + * + * Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of + * operation defined in SP 800-38a. It can be used with any block + * cipher to provide confidentiality of strings whose lengths are + * multiples of the block_size of the underlying block cipher. + * TinyCrypt hard codes AES as the block cipher. + * + * Security: CBC mode provides data confidentiality given that the maximum + * number q of blocks encrypted under a single key satisfies + * q < 2^63, which is not a practical constraint (it is considered a + * good practice to replace the encryption when q == 2^56). CBC mode + * provides NO data integrity. + * + * CBC mode assumes that the IV value input into the + * tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library + * provides HMAC-PRNG module, which generates suitable IVs. Other + * methods for generating IVs are acceptable, provided that the + * values of the IVs generated appear random to any adversary, + * including someone with complete knowledge of the system design. + * + * The randomness property on which CBC mode's security depends is + * the unpredictability of the IV. Since it is unpredictable, this + * means in practice that CBC mode requires that the IV is stored + * somehow with the ciphertext in order to recover the plaintext. + * + * TinyCrypt CBC encryption prepends the IV to the ciphertext, + * because this affords a more efficient (few buffers) decryption. + * Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always + * 16 bytes larger than the plaintext buffer. + * + * Requires: AES-128 + * + * Usage: 1) call tc_cbc_mode_encrypt to encrypt data. + * + * 2) call tc_cbc_mode_decrypt to decrypt data. + * + */ + +#ifndef __TC_CBC_MODE_H__ +#define __TC_CBC_MODE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CBC encryption procedure + * CBC encrypts inlen bytes of the in buffer into the out buffer + * using the encryption key schedule provided, prepends iv to out + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * ctr == NULL or + * sched == NULL or + * inlen == 0 or + * (inlen % TC_AES_BLOCK_SIZE) != 0 or + * (outlen % TC_AES_BLOCK_SIZE) != 0 or + * outlen != inlen + TC_AES_BLOCK_SIZE + * @note Assumes: - sched has been configured by aes_set_encrypt_key + * - iv contains a 16 byte random string + * - out buffer is large enough to hold the ciphertext + iv + * - out buffer is a contiguous buffer + * - in holds the plaintext and is a contiguous buffer + * - inlen gives the number of bytes in the in buffer + * @param out IN/OUT -- buffer to receive the ciphertext + * @param outlen IN -- length of ciphertext buffer in bytes + * @param in IN -- plaintext to encrypt + * @param inlen IN -- length of plaintext buffer in bytes + * @param iv IN -- the IV for the this encrypt/decrypt + * @param sched IN -- AES key schedule for this encrypt + */ +int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched); + +/** + * @brief CBC decryption procedure + * CBC decrypts inlen bytes of the in buffer into the out buffer + * using the provided encryption key schedule + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * sched == NULL or + * inlen == 0 or + * outlen == 0 or + * (inlen % TC_AES_BLOCK_SIZE) != 0 or + * (outlen % TC_AES_BLOCK_SIZE) != 0 or + * outlen != inlen + TC_AES_BLOCK_SIZE + * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are + * contiguous. This allows for a very efficient decryption + * algorithm that would not otherwise be possible + * - sched was configured by aes_set_decrypt_key + * - out buffer is large enough to hold the decrypted plaintext + * and is a contiguous buffer + * - inlen gives the number of bytes in the in buffer + * @param out IN/OUT -- buffer to receive decrypted data + * @param outlen IN -- length of plaintext buffer in bytes + * @param in IN -- ciphertext to decrypt, including IV + * @param inlen IN -- length of ciphertext buffer in bytes + * @param iv IN -- the IV for the this encrypt/decrypt + * @param sched IN -- AES key schedule for this decrypt + * + */ +int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CBC_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h new file mode 100644 index 0000000000..69c798e2f5 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h @@ -0,0 +1,211 @@ +/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CCM mode implementation. + * + * Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of + * operation defined in SP 800-38C. + * + * TinyCrypt CCM implementation accepts: + * + * 1) Both non-empty payload and associated data (it encrypts and + * authenticates the payload and also authenticates the associated + * data); + * 2) Non-empty payload and empty associated data (it encrypts and + * authenticates the payload); + * 3) Non-empty associated data and empty payload (it degenerates to + * an authentication mode on the associated data). + * + * TinyCrypt CCM implementation accepts associated data of any length + * between 0 and (2^16 - 2^8) bytes. + * + * Security: The mac length parameter is an important parameter to estimate the + * security against collision attacks (that aim at finding different + * messages that produce the same authentication tag). TinyCrypt CCM + * implementation accepts any even integer between 4 and 16, as + * suggested in SP 800-38C. + * + * RFC-3610, which also specifies CCM, presents a few relevant + * security suggestions, such as: it is recommended for most + * applications to use a mac length greater than 8. Besides, the + * usage of the same nonce for two different messages which are + * encrypted with the same key destroys the security of CCM mode. + * + * Requires: AES-128 + * + * Usage: 1) call tc_ccm_config to configure. + * + * 2) call tc_ccm_mode_encrypt to encrypt data and generate tag. + * + * 3) call tc_ccm_mode_decrypt to decrypt data and verify tag. + */ + +#ifndef __TC_CCM_MODE_H__ +#define __TC_CCM_MODE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */ +#define TC_CCM_AAD_MAX_BYTES 0xff00 + +/* max message size in bytes: 2^(8L) = 2^16 = 65536 */ +#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000 + +/* struct tc_ccm_mode_struct represents the state of a CCM computation */ +typedef struct tc_ccm_mode_struct { + TCAesKeySched_t sched; /* AES key schedule */ + uint8_t *nonce; /* nonce required by CCM */ + unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */ +} *TCCcmMode_t; + +/** + * @brief CCM configuration procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * c == NULL or + * sched == NULL or + * nonce == NULL or + * mlen != {4, 6, 8, 10, 12, 16} + * @param c -- CCM state + * @param sched IN -- AES key schedule + * @param nonce IN - nonce + * @param nlen -- nonce length in bytes + * @param mlen -- mac length in bytes (parameter t in SP-800 38C) + */ +int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, + unsigned int nlen, unsigned int mlen); + +/** + * @brief CCM tag generation and encryption procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * c == NULL or + * ((plen > 0) and (payload == NULL)) or + * ((alen > 0) and (associated_data == NULL)) or + * (alen >= TC_CCM_AAD_MAX_BYTES) or + * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or + * (olen < plen + maclength) + * + * @param out OUT -- encrypted data + * @param olen IN -- output length in bytes + * @param associated_data IN -- associated data + * @param alen IN -- associated data length in bytes + * @param payload IN -- payload + * @param plen IN -- payload length in bytes + * @param c IN -- CCM state + * + * @note: out buffer should be at least (plen + c->mlen) bytes long. + * + * @note: The sequence b for encryption is formatted as follows: + * b = [FLAGS | nonce | counter ], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * counter is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-7 btis: always 0's + * + * @note: The sequence b for authentication is formatted as follows: + * b = [FLAGS | nonce | length(mac length)], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * length(mac length) is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-5 bits: mac length (encoded as: (mlen-2)/2) + * 6: Adata (0 if alen == 0, and 1 otherwise) + * 7: always 0 + */ +int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c); + +/** + * @brief CCM decryption and tag verification procedure + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * c == NULL or + * ((plen > 0) and (payload == NULL)) or + * ((alen > 0) and (associated_data == NULL)) or + * (alen >= TC_CCM_AAD_MAX_BYTES) or + * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or + * (olen < plen - c->mlen) + * + * @param out OUT -- decrypted data + * @param associated_data IN -- associated data + * @param alen IN -- associated data length in bytes + * @param payload IN -- payload + * @param plen IN -- payload length in bytes + * @param c IN -- CCM state + * + * @note: out buffer should be at least (plen - c->mlen) bytes long. + * + * @note: The sequence b for encryption is formatted as follows: + * b = [FLAGS | nonce | counter ], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * counter is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-7 btis: always 0's + * + * @note: The sequence b for authentication is formatted as follows: + * b = [FLAGS | nonce | length(mac length)], where: + * FLAGS is 1 byte long + * nonce is 13 bytes long + * length(mac length) is 2 bytes long + * The byte FLAGS is composed by the following 8 bits: + * 0-2 bits: used to represent the value of q-1 + * 3-5 bits: mac length (encoded as: (mlen-2)/2) + * 6: Adata (0 if alen == 0, and 1 otherwise) + * 7: always 0 + */ +int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, unsigned int plen, + TCCcmMode_t c); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CCM_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h new file mode 100644 index 0000000000..f44b0a53c1 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h @@ -0,0 +1,194 @@ +/* cmac_mode.h -- interface to a CMAC implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CMAC implementation. + * + * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm + * for computing a MAC using a block cipher. It can compute the MAC + * for a byte string of any length. It is distinguished from CBC-MAC + * in the processing of the final message block; CMAC uses a + * different technique to compute the final message block is full + * size or only partial, while CBC-MAC uses the same technique for + * both. This difference permits CMAC to be applied to variable + * length messages, while all messages authenticated by CBC-MAC must + * be the same length. + * + * Security: AES128-CMAC mode of operation offers 64 bits of security against + * collision attacks. Note however that an external attacker cannot + * generate the tags him/herself without knowing the MAC key. In this + * sense, to attack the collision property of AES128-CMAC, an + * external attacker would need the cooperation of the legal user to + * produce an exponentially high number of tags (e.g. 2^64) to + * finally be able to look for collisions and benefit from them. As + * an extra precaution, the current implementation allows to at most + * 2^48 calls to the tc_cmac_update function before re-calling + * tc_cmac_setup (allowing a new key to be set), as suggested in + * Appendix B of SP 800-38B. + * + * Requires: AES-128 + * + * Usage: This implementation provides a "scatter-gather" interface, so that + * the CMAC value can be computed incrementally over a message + * scattered in different segments throughout memory. Experience shows + * this style of interface tends to minimize the burden of programming + * correctly. Like all symmetric key operations, it is session + * oriented. + * + * To begin a CMAC session, use tc_cmac_setup to initialize a struct + * tc_cmac_struct with encryption key and buffer. Our implementation + * always assume that the AES key to be the same size as the block + * cipher block size. Once setup, this data structure can be used for + * many CMAC computations. + * + * Once the state has been setup with a key, computing the CMAC of + * some data requires three steps: + * + * (1) first use tc_cmac_init to initialize a new CMAC computation. + * (2) next mix all of the data into the CMAC computation state using + * tc_cmac_update. If all of the data resides in a single data + * segment then only one tc_cmac_update call is needed; if data + * is scattered throughout memory in n data segments, then n calls + * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect + * attacks that swap bytes, so the order in which data is mixed + * into the state is critical! + * (3) Once all of the data for a message has been mixed, use + * tc_cmac_final to compute the CMAC tag value. + * + * Steps (1)-(3) can be repeated as many times as you want to CMAC + * multiple messages. A practical limit is 2^48 1K messages before you + * have to change the key. + * + * Once you are done computing CMAC with a key, it is a good idea to + * destroy the state so an attacker cannot recover the key; use + * tc_cmac_erase to accomplish this. + */ + +#ifndef __TC_CMAC_MODE_H__ +#define __TC_CMAC_MODE_H__ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* padding for last message block */ +#define TC_CMAC_PADDING 0x80 + +/* struct tc_cmac_struct represents the state of a CMAC computation */ +typedef struct tc_cmac_struct { +/* initialization vector */ + uint8_t iv[TC_AES_BLOCK_SIZE]; +/* used if message length is a multiple of block_size bytes */ + uint8_t K1[TC_AES_BLOCK_SIZE]; +/* used if message length isn't a multiple block_size bytes */ + uint8_t K2[TC_AES_BLOCK_SIZE]; +/* where to put bytes that didn't fill a block */ + uint8_t leftover[TC_AES_BLOCK_SIZE]; +/* identifies the encryption key */ + unsigned int keyid; +/* next available leftover location */ + unsigned int leftover_offset; +/* AES key schedule */ + TCAesKeySched_t sched; +/* calls to tc_cmac_update left before re-key */ + uint64_t countdown; +} *TCCmacState_t; + +/** + * @brief Configures the CMAC state to use the given AES key + * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL or + * key == NULL + * + * @param s IN/OUT -- the state to set up + * @param key IN -- the key to use + * @param sched IN -- AES key schedule + */ +int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, + TCAesKeySched_t sched); + +/** + * @brief Erases the CMAC state + * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL + * + * @param s IN/OUT -- the state to erase + */ +int tc_cmac_erase(TCCmacState_t s); + +/** + * @brief Initializes a new CMAC computation + * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL + * + * @param s IN/OUT -- the state to initialize + */ +int tc_cmac_init(TCCmacState_t s); + +/** + * @brief Incrementally computes CMAC over the next data segment + * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL or + * if data == NULL when dlen > 0 + * + * @param s IN/OUT -- the CMAC state + * @param data IN -- the next data segment to MAC + * @param dlen IN -- the length of data in bytes + */ +int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen); + +/** + * @brief Generates the tag from the CMAC state + * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag + * returns TC_CRYPTO_FAIL (0) if: + * tag == NULL or + * s == NULL + * + * @param tag OUT -- the CMAC tag + * @param s IN -- CMAC state + */ +int tc_cmac_final(uint8_t *tag, TCCmacState_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CMAC_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h new file mode 100644 index 0000000000..965490e00c --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h @@ -0,0 +1,61 @@ +/* constants.h - TinyCrypt interface to constants */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to constants. + * + */ + +#ifndef __TC_CONSTANTS_H__ +#define __TC_CONSTANTS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define TC_CRYPTO_SUCCESS 1 +#define TC_CRYPTO_FAIL 0 + +#define TC_ZERO_BYTE 0x00 + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CONSTANTS_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h new file mode 100644 index 0000000000..dc221f9ee7 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h @@ -0,0 +1,108 @@ +/* ctr_mode.h - TinyCrypt interface to CTR mode */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to CTR mode. + * + * Overview: CTR (pronounced "counter") mode is a NIST approved mode of + * operation defined in SP 800-38a. It can be used with any + * block cipher to provide confidentiality of strings of any + * length. TinyCrypt hard codes AES128 as the block cipher. + * + * Security: CTR mode achieves confidentiality only if the counter value is + * never reused with a same encryption key. If the counter is + * repeated, than an adversary might be able to defeat the scheme. + * + * A usual method to ensure different counter values refers to + * initialize the counter in a given value (0, for example) and + * increases it every time a new block is enciphered. This naturally + * leaves to a limitation on the number q of blocks that can be + * enciphered using a same key: q < 2^(counter size). + * + * TinyCrypt uses a counter of 32 bits. This means that after 2^32 + * block encryptions, the counter will be reused (thus losing CBC + * security). 2^32 block encryptions should be enough for most of + * applications targeting constrained devices. Applications intended + * to encrypt a larger number of blocks must replace the key after + * 2^32 block encryptions. + * + * CTR mode provides NO data integrity. + * + * Requires: AES-128 + * + * Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt. + * + */ + +#ifndef __TC_CTR_MODE_H__ +#define __TC_CTR_MODE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief CTR mode encryption/decryption procedure. + * CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL or + * in == NULL or + * ctr == NULL or + * sched == NULL or + * inlen == 0 or + * outlen == 0 or + * inlen != outlen + * @note Assumes:- The current value in ctr has NOT been used with sched + * - out points to inlen bytes + * - in points to inlen bytes + * - ctr is an integer counter in littleEndian format + * - sched was initialized by aes_set_encrypt_key + * @param out OUT -- produced ciphertext (plaintext) + * @param outlen IN -- length of ciphertext buffer in bytes + * @param in IN -- data to encrypt (or decrypt) + * @param inlen IN -- length of input data in bytes + * @param ctr IN/OUT -- the current counter value + * @param sched IN -- an initialized AES key schedule + */ +int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CTR_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h new file mode 100644 index 0000000000..9be06dbb16 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h @@ -0,0 +1,166 @@ +/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */ + +/* + * Copyright (c) 2016, Chris Morrison + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a CTR-PRNG implementation. + * + * Overview: A pseudo-random number generator (PRNG) generates a sequence + * of numbers that have a distribution close to the one expected + * for a sequence of truly random numbers. The NIST Special + * Publication 800-90A specifies several mechanisms to generate + * sequences of pseudo random numbers, including the CTR-PRNG one + * which is based on AES. TinyCrypt implements CTR-PRNG with + * AES-128. + * + * Security: A cryptographically secure PRNG depends on the existence of an + * entropy source to provide a truly random seed as well as the + * security of the primitives used as the building blocks (AES-128 + * in this instance). + * + * Requires: - AES-128 + * + * Usage: 1) call tc_ctr_prng_init to seed the prng context + * + * 2) call tc_ctr_prng_reseed to mix in additional entropy into + * the prng context + * + * 3) call tc_ctr_prng_generate to output the pseudo-random data + * + * 4) call tc_ctr_prng_uninstantiate to zero out the prng context + */ + +#ifndef __TC_CTR_PRNG_H__ +#define __TC_CTR_PRNG_H__ + +#include + +#define TC_CTR_PRNG_RESEED_REQ -1 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + /* updated each time another BLOCKLEN_BYTES bytes are produced */ + uint8_t V[TC_AES_BLOCK_SIZE]; + + /* updated whenever the PRNG is reseeded */ + struct tc_aes_key_sched_struct key; + + /* number of requests since initialization/reseeding */ + uint64_t reseedCount; +} TCCtrPrng_t; + + +/** + * @brief CTR-PRNG initialization procedure + * Initializes prng context with entropy and personalization string (if any) + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * entropy == NULL, + * entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) + * @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of + * both the entropy and personalization inputs are used - + * supplying additional bytes has no effect. + * @param ctx IN/OUT -- the PRNG context to initialize + * @param entropy IN -- entropy used to seed the PRNG + * @param entropyLen IN -- entropy length in bytes + * @param personalization IN -- personalization string used to seed the PRNG + * (may be null) + * @param plen IN -- personalization length in bytes + * + */ +int tc_ctr_prng_init(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const personalization, + unsigned int pLen); + +/** + * @brief CTR-PRNG reseed procedure + * Mixes entropy and additional_input into the prng context + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * entropy == NULL, + * entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) + * @note It is better to reseed an existing prng context rather than + * re-initialise, so that any existing entropy in the context is + * presereved. This offers some protection against undetected failures + * of the entropy source. + * @note Assumes tc_ctr_prng_init has been called for ctx + * @param ctx IN/OUT -- the PRNG state + * @param entropy IN -- entropy to mix into the prng + * @param entropylen IN -- length of entropy in bytes + * @param additional_input IN -- additional input to the prng (may be null) + * @param additionallen IN -- additional input length in bytes + */ +int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const additional_input, + unsigned int additionallen); + +/** + * @brief CTR-PRNG generate procedure + * Generates outlen pseudo-random bytes into out buffer, updates prng + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed + * returns TC_CRYPTO_FAIL (0) if: + * ctx == NULL, + * out == NULL, + * outlen >= 2^16 + * @note Assumes tc_ctr_prng_init has been called for ctx + * @param ctx IN/OUT -- the PRNG context + * @param additional_input IN -- additional input to the prng (may be null) + * @param additionallen IN -- additional input length in bytes + * @param out IN/OUT -- buffer to receive output + * @param outlen IN -- size of out buffer in bytes + */ +int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, + uint8_t const * const additional_input, + unsigned int additionallen, + uint8_t * const out, + unsigned int outlen); + +/** + * @brief CTR-PRNG uninstantiate procedure + * Zeroes the internal state of the supplied prng context + * @return none + * @param ctx IN/OUT -- the PRNG context + */ +void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_CTR_PRNG_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h index 045fd983f6..8abc949cc6 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h @@ -1,478 +1,545 @@ -/* ecc.h - TinyCrypt interface to common ECC functions */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to common ECC functions. - * - * Overview: This software is an implementation of common functions - * necessary to elliptic curve cryptography. This implementation uses - * curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - * - */ - -#ifndef __TC_UECC_H__ -#define __TC_UECC_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Return values for functions, chosen with large Hamming distances between - * them (especially to SUCESS) to mitigate the impact of fault injection - * attacks flipping a low number of bits. */ -#define UECC_SUCCESS 0xCD -#define UECC_FAILURE 0x52 -#define UECC_FAULT_DETECTED 0x3B - -/* Word size (4 bytes considering 32-bits architectures) */ -#define uECC_WORD_SIZE 4 - -/* setting max number of calls to prng: */ -#ifndef uECC_RNG_MAX_TRIES -#define uECC_RNG_MAX_TRIES 64 -#endif - -/* defining data types to store word and bit counts: */ -typedef int_fast8_t wordcount_t; -typedef int_fast16_t bitcount_t; -/* defining data type for comparison result: */ -typedef int_fast8_t cmpresult_t; -/* defining data type to store ECC coordinate/point in 32bits words: */ -typedef unsigned int uECC_word_t; -/* defining data type to store an ECC coordinate/point in 64bits words: */ -typedef uint64_t uECC_dword_t; - -/* defining masks useful for ecc computations: */ -#define HIGH_BIT_SET 0x80000000 -#define uECC_WORD_BITS 32 -#define uECC_WORD_BITS_SHIFT 5 -#define uECC_WORD_BITS_MASK 0x01F - -/* Number of words of 32 bits to represent an element of the the curve p-256: */ -#define NUM_ECC_WORDS 8 -/* Number of bytes to represent an element of the the curve p-256: */ -#define NUM_ECC_BYTES (uECC_WORD_SIZE * NUM_ECC_WORDS) -#define NUM_ECC_BITS 256 - -/* - * @brief computes doubling of point ion jacobian coordinates, in place. - * @param X1 IN/OUT -- x coordinate - * @param Y1 IN/OUT -- y coordinate - * @param Z1 IN/OUT -- z coordinate - * @param curve IN -- elliptic curve - */ -void double_jacobian_default(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *Z1); - -/* - * @brief Computes result = product % curve_p - * from http://www.nsa.gov/ia/_files/nist-routines.pdf - * @param result OUT -- product % curve_p - * @param product IN -- value to be reduced mod curve_p - */ -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product); - -/* Bytes to words ordering: */ -#define TC_BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \ - 0x##d##c##b##a, 0x##h##g##f##e -#define TC_BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a -#define TC_BITS_TO_WORDS(num_bits) \ - ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) -#define TC_BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) - -extern const uECC_word_t curve_p[NUM_ECC_WORDS]; -extern const uECC_word_t curve_n[NUM_ECC_WORDS]; -extern const uECC_word_t curve_G[2 * NUM_ECC_WORDS]; -extern const uECC_word_t curve_b[NUM_ECC_WORDS]; - -/* - * @brief Generates a random integer in the range 0 < random < top. - * Both random and top have num_words words. - * @param random OUT -- random integer in the range 0 < random < top - * @param top IN -- upper limit - * @param num_words IN -- number of words - * @return UECC_SUCCESS in case of success - * @return UECC_FAILURE upon failure - */ -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words); - -/* uECC_RNG_Function type - * The RNG function should fill 'size' random bytes into 'dest'. It should - * return 'size' if 'dest' was filled with random data of 'size' length, or 0 - * if the random data could not be generated. The filled-in values should be - * either truly random, or from a cryptographically-secure PRNG. - * - * A correctly functioning RNG function must be set (using uECC_set_rng()) - * before calling uECC_make_key() or uECC_sign(). - * - * Setting a correctly functioning RNG function improves the resistance to - * side-channel attacks for uECC_shared_secret(). - * - * A correct RNG function is set by default. If you are building on another - * POSIX-compliant system that supports /dev/random or /dev/urandom, you can - * define uECC_POSIX to use the predefined RNG. - */ -typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned int size); - -/* - * @brief Set the function that will be used to generate random bytes. The RNG - * function should return 'size' if the random data of length 'size' was - * generated, or 0 if the random data could not be generated. - * - * @note On platforms where there is no predefined RNG function, this must be - * called before uECC_make_key() or uECC_sign() are used. - * - * @param rng_function IN -- function that will be used to generate random bytes - */ -void uECC_set_rng(uECC_RNG_Function rng_function); - -/* - * @brief provides current uECC_RNG_Function. - * @return Returns the function that will be used to generate random bytes. - */ -uECC_RNG_Function uECC_get_rng(void); - -/* - * @brief computes the size of a private key for the curve in bytes. - * @param curve IN -- elliptic curve - * @return size of a private key for the curve in bytes. - */ -int uECC_curve_private_key_size(void); - -/* - * @brief computes the size of a public key for the curve in bytes. - * @param curve IN -- elliptic curve - * @return the size of a public key for the curve in bytes. - */ -int uECC_curve_public_key_size(void); - -/* - * @brief Compute the corresponding public key for a private key. - * @param private_key IN -- The private key to compute the public key for - * @param public_key OUT -- Will be filled in with the corresponding public key - * @param curve - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - */ -int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key); - -/* - * @brief Compute public-key. - * @return corresponding public-key. - * @param result OUT -- public-key - * @param private_key IN -- private-key - * @param curve IN -- elliptic curve - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - */ -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key); - -/* - * @brief Point multiplication algorithm using Montgomery's ladder with co-Z - * coordinates. See http://eprint.iacr.org/2011/338.pdf. - * Uses scalar regularization and coordinate randomization (if a global RNG - * function is set) in order to protect against some side channel attacks. - * @note Result may overlap point. - * @param result OUT -- returns scalar*point - * @param point IN -- elliptic curve point - * @param scalar IN -- scalar - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - */ -int EccPoint_mult_safer(uECC_word_t *result, const uECC_word_t *point, - const uECC_word_t *scalar); - -/* - * @brief Constant-time comparison to zero - secure way to compare long integers - * @param vli IN -- very long integer - * @param num_words IN -- number of words in the vli - * @return 1 if vli == 0, 0 otherwise. - */ -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli); - -/* - * @brief Check if 'point' is the point at infinity - * @param point IN -- elliptic curve point - * @return if 'point' is the point at infinity, 0 otherwise. - */ -uECC_word_t EccPoint_isZero(const uECC_word_t *point); - -/* - * @brief computes the sign of left - right, in constant time. - * @param left IN -- left term to be compared - * @param right IN -- right term to be compared - * @param num_words IN -- number of words - * @return the sign of left - right - */ -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right); - -/* - * @brief computes sign of left - right, not in constant time. - * @note should not be used if inputs are part of a secret - * @param left IN -- left term to be compared - * @param right IN -- right term to be compared - * @param num_words IN -- number of words - * @return the sign of left - right - */ -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, - const uECC_word_t *right); - -/* - * @brief Computes result = (left - right) % mod. - * @note Assumes that (left < mod) and (right < mod), and that result does not - * overlap mod. - * @param result OUT -- (left - right) % mod - * @param left IN -- leftright term in modular subtraction - * @param right IN -- right term in modular subtraction - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod); - -/* - * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or - * P => P', Q => P + Q - * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z) - * @param X1 IN -- x coordinate of P - * @param Y1 IN -- y coordinate of P - * @param X2 IN -- x coordinate of Q - * @param Y2 IN -- y coordinate of Q - * @param curve IN -- elliptic curve - */ -void XYcZ_add(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, - uECC_word_t *Y2); - -/* - * @brief Computes (x1 * z^2, y1 * z^3) - * @param X1 IN -- previous x1 coordinate - * @param Y1 IN -- previous y1 coordinate - * @param Z IN -- z value - * @param curve IN -- elliptic curve - */ -void apply_z(uECC_word_t *X1, uECC_word_t *Y1, const uECC_word_t *const Z); - -/* - * @brief Check if bit is set. - * @return Returns nonzero if bit 'bit' of vli is set. - * @warning It is assumed that the value provided in 'bit' is within the - * boundaries of the word-array 'vli'. - * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0}, - * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting - * of 4 uECC_word_t elements. - */ -uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); - -/* - * @brief Computes result = product % mod, where product is 2N words long. - * @param result OUT -- product % mod - * @param mod IN -- module - * @param num_words IN -- number of words - * @warning Currently only designed to work for curve_p or curve_n. - */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod); - -/* - * @brief Computes modular product (using curve->mmod_fast) - * @param result OUT -- (left * right) mod % curve_p - * @param left IN -- left term in product - * @param right IN -- right term in product - * @param curve IN -- elliptic curve - */ -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right); - -/* - * @brief Computes result = left - right. - * @note Can modify in place. - * @param result OUT -- left - right - * @param left IN -- left term in subtraction - * @param right IN -- right term in subtraction - * @param num_words IN -- number of words - * @return borrow - */ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right); - -/* - * @brief Constant-time comparison function(secure way to compare long ints) - * @param left IN -- left term in comparison - * @param right IN -- right term in comparison - * @param num_words IN -- number of words - * @return Returns 0 if left == right, non-zero otherwise. - */ -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right); - -/* - * @brief Computes (left * right) % mod - * @param result OUT -- (left * right) % mod - * @param left IN -- left term in product - * @param right IN -- right term in product - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod); - -/* - * @brief Computes (1 / input) % mod - * @note All VLIs are the same size. - * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide" - * @param result OUT -- (1 / input) % mod - * @param input IN -- value to be modular inverted - * @param mod IN -- mod - * @param num_words -- number of words - */ -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod); - -/* - * @brief Sets dest = src. - * @param dest OUT -- destination buffer - * @param src IN -- origin buffer - * @param num_words IN -- number of words - */ -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src); - -/* - * @brief Computes (left + right) % mod. - * @note Assumes that (left < mod) and right < mod), and that result does not - * overlap mod. - * @param result OUT -- (left + right) % mod. - * @param left IN -- left term in addition - * @param right IN -- right term in addition - * @param mod IN -- mod - * @param num_words IN -- number of words - */ -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod); - -/* - * @brief Counts the number of bits required to represent vli. - * @param vli IN -- very long integer - * @param max_words IN -- number of words - * @return number of bits in given vli - */ -bitcount_t uECC_vli_numBits(const uECC_word_t *vli); - -/* - * @brief Erases (set to 0) vli - * @param vli IN -- very long integer - * @param num_words IN -- number of words - */ -void uECC_vli_clear(uECC_word_t *vli); - -/* - * @brief check if it is a valid point in the curve - * @param point IN -- point to be checked - * @param curve IN -- elliptic curve - * @return 0 if point is valid - * @exception returns -1 if it is a point at infinity - * @exception returns -2 if x or y is smaller than p, - * @exception returns -3 if y^2 != x^3 + ax + b. - */ -int uECC_valid_point(const uECC_word_t *point); - -/* - * @brief Check if a public key is valid. - * @param public_key IN -- The public key to be checked. - * @return returns 0 if the public key is valid - * @exception returns -1 if it is a point at infinity - * @exception returns -2 if x or y is smaller than p, - * @exception returns -3 if y^2 != x^3 + ax + b. - * @exception returns -4 if public key is the group generator. - * - * @note Note that you are not required to check for a valid public key before - * using any other uECC functions. However, you may wish to avoid spending CPU - * time computing a shared secret or verifying a signature using an invalid - * public key. - */ -int uECC_valid_public_key(const uint8_t *public_key); - -/* - * @brief Converts an integer in uECC native format to big-endian bytes. - * @param bytes OUT -- bytes representation - * @param num_bytes IN -- number of bytes - * @param native IN -- uECC native representation - */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native); - -/* - * @brief Converts big-endian bytes to an integer in uECC native format. - * @param native OUT -- uECC native representation - * @param bytes IN -- bytes representation - * @param num_bytes IN -- number of bytes - */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_UECC_H__ */ +/* ecc.h - TinyCrypt interface to common ECC functions */ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to common ECC functions. + * + * Overview: This software is an implementation of common functions + * necessary to elliptic curve cryptography. This implementation uses + * curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + * + */ + +#ifndef __TC_UECC_H__ +#define __TC_UECC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Word size (4 bytes considering 32-bits architectures) */ +#define uECC_WORD_SIZE 4 + +/* setting max number of calls to prng: */ +#ifndef uECC_RNG_MAX_TRIES +#define uECC_RNG_MAX_TRIES 64 +#endif + +/* defining data types to store word and bit counts: */ +typedef int8_t wordcount_t; +typedef int16_t bitcount_t; +/* defining data type for comparison result: */ +typedef int8_t cmpresult_t; +/* defining data type to store ECC coordinate/point in 32bits words: */ +typedef unsigned int uECC_word_t; +/* defining data type to store an ECC coordinate/point in 64bits words: */ +typedef uint64_t uECC_dword_t; + +/* defining masks useful for ecc computations: */ +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 +#define uECC_WORD_BITS_SHIFT 5 +#define uECC_WORD_BITS_MASK 0x01F + +/* Number of words of 32 bits to represent an element of the the curve p-256: */ +#define NUM_ECC_WORDS 8 +/* Number of bytes to represent an element of the the curve p-256: */ +#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS) + +/* structure that represents an elliptic curve (e.g. p256):*/ +struct uECC_Curve_t; +typedef const struct uECC_Curve_t * uECC_Curve; +struct uECC_Curve_t { + wordcount_t num_words; + wordcount_t num_bytes; + bitcount_t num_n_bits; + uECC_word_t p[NUM_ECC_WORDS]; + uECC_word_t n[NUM_ECC_WORDS]; + uECC_word_t G[NUM_ECC_WORDS * 2]; + uECC_word_t b[NUM_ECC_WORDS]; + void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1, + uECC_Curve curve); + void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); + void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); +}; + +/* + * @brief computes doubling of point ion jacobian coordinates, in place. + * @param X1 IN/OUT -- x coordinate + * @param Y1 IN/OUT -- y coordinate + * @param Z1 IN/OUT -- z coordinate + * @param curve IN -- elliptic curve + */ +void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * Z1, uECC_Curve curve); + +/* + * @brief Computes x^3 + ax + b. result must not overlap x. + * @param result OUT -- x^3 + ax + b + * @param x IN -- value of x + * @param curve IN -- elliptic curve + */ +void x_side_default(uECC_word_t *result, const uECC_word_t *x, + uECC_Curve curve); + +/* + * @brief Computes result = product % curve_p + * from http://www.nsa.gov/ia/_files/nist-routines.pdf + * @param result OUT -- product % curve_p + * @param product IN -- value to be reduced mod curve_p + */ +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product); + +/* Bytes to words ordering: */ +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a +#define BITS_TO_WORDS(num_bits) \ + ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) +#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) + +/* definition of curve NIST p-256: */ +static const struct uECC_Curve_t curve_secp256r1 = { + NUM_ECC_WORDS, + NUM_ECC_BYTES, + 256, /* num_n_bits */ { + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) + }, { + BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) + }, { + BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), + BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), + BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), + BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), + BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) + }, { + BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) + }, + &double_jacobian_default, + &x_side_default, + &vli_mmod_fast_secp256r1 +}; + +uECC_Curve uECC_secp256r1(void); + +/* + * @brief Generates a random integer in the range 0 < random < top. + * Both random and top have num_words words. + * @param random OUT -- random integer in the range 0 < random < top + * @param top IN -- upper limit + * @param num_words IN -- number of words + * @return a random integer in the range 0 < random < top + */ +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, + wordcount_t num_words); + + +/* uECC_RNG_Function type + * The RNG function should fill 'size' random bytes into 'dest'. It should + * return 1 if 'dest' was filled with random data, or 0 if the random data could + * not be generated. The filled-in values should be either truly random, or from + * a cryptographically-secure PRNG. + * + * A correctly functioning RNG function must be set (using uECC_set_rng()) + * before calling uECC_make_key() or uECC_sign(). + * + * Setting a correctly functioning RNG function improves the resistance to + * side-channel attacks for uECC_shared_secret(). + * + * A correct RNG function is set by default. If you are building on another + * POSIX-compliant system that supports /dev/random or /dev/urandom, you can + * define uECC_POSIX to use the predefined RNG. + */ +typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size); + +/* + * @brief Set the function that will be used to generate random bytes. The RNG + * function should return 1 if the random data was generated, or 0 if the random + * data could not be generated. + * + * @note On platforms where there is no predefined RNG function, this must be + * called before uECC_make_key() or uECC_sign() are used. + * + * @param rng_function IN -- function that will be used to generate random bytes + */ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* + * @brief provides current uECC_RNG_Function. + * @return Returns the function that will be used to generate random bytes. + */ +uECC_RNG_Function uECC_get_rng(void); + +/* + * @brief computes the size of a private key for the curve in bytes. + * @param curve IN -- elliptic curve + * @return size of a private key for the curve in bytes. + */ +int uECC_curve_private_key_size(uECC_Curve curve); + +/* + * @brief computes the size of a public key for the curve in bytes. + * @param curve IN -- elliptic curve + * @return the size of a public key for the curve in bytes. + */ +int uECC_curve_public_key_size(uECC_Curve curve); + +/* + * @brief Compute the corresponding public key for a private key. + * @param private_key IN -- The private key to compute the public key for + * @param public_key OUT -- Will be filled in with the corresponding public key + * @param curve + * @return Returns 1 if key was computed successfully, 0 if an error occurred. + */ +int uECC_compute_public_key(const uint8_t *private_key, + uint8_t *public_key, uECC_Curve curve); + +/* + * @brief Compute public-key. + * @return corresponding public-key. + * @param result OUT -- public-key + * @param private_key IN -- private-key + * @param curve IN -- elliptic curve + */ +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, uECC_Curve curve); + +/* + * @brief Regularize the bitcount for the private key so that attackers cannot + * use a side channel attack to learn the number of leading zeros. + * @return Regularized k + * @param k IN -- private-key + * @param k0 IN/OUT -- regularized k + * @param k1 IN/OUT -- regularized k + * @param curve IN -- elliptic curve + */ +uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, + uECC_word_t *k1, uECC_Curve curve); + +/* + * @brief Point multiplication algorithm using Montgomery's ladder with co-Z + * coordinates. See http://eprint.iacr.org/2011/338.pdf. + * @note Result may overlap point. + * @param result OUT -- returns scalar*point + * @param point IN -- elliptic curve point + * @param scalar IN -- scalar + * @param initial_Z IN -- initial value for z + * @param num_bits IN -- number of bits in scalar + * @param curve IN -- elliptic curve + */ +void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, const uECC_word_t * initial_Z, + bitcount_t num_bits, uECC_Curve curve); + +/* + * @brief Constant-time comparison to zero - secure way to compare long integers + * @param vli IN -- very long integer + * @param num_words IN -- number of words in the vli + * @return 1 if vli == 0, 0 otherwise. + */ +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); + +/* + * @brief Check if 'point' is the point at infinity + * @param point IN -- elliptic curve point + * @param curve IN -- elliptic curve + * @return if 'point' is the point at infinity, 0 otherwise. + */ +uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); + +/* + * @brief computes the sign of left - right, in constant time. + * @param left IN -- left term to be compared + * @param right IN -- right term to be compared + * @param num_words IN -- number of words + * @return the sign of left - right + */ +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief computes sign of left - right, not in constant time. + * @note should not be used if inputs are part of a secret + * @param left IN -- left term to be compared + * @param right IN -- right term to be compared + * @param num_words IN -- number of words + * @return the sign of left - right + */ +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief Computes result = (left - right) % mod. + * @note Assumes that (left < mod) and (right < mod), and that result does not + * overlap mod. + * @param result OUT -- (left - right) % mod + * @param left IN -- leftright term in modular subtraction + * @param right IN -- right term in modular subtraction + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or + * P => P', Q => P + Q + * @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z) + * @param X1 IN -- x coordinate of P + * @param Y1 IN -- y coordinate of P + * @param X2 IN -- x coordinate of Q + * @param Y2 IN -- y coordinate of Q + * @param curve IN -- elliptic curve + */ +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, + uECC_word_t * Y2, uECC_Curve curve); + +/* + * @brief Computes (x1 * z^2, y1 * z^3) + * @param X1 IN -- previous x1 coordinate + * @param Y1 IN -- previous y1 coordinate + * @param Z IN -- z value + * @param curve IN -- elliptic curve + */ +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, + uECC_Curve curve); + +/* + * @brief Check if bit is set. + * @return Returns nonzero if bit 'bit' of vli is set. + * @warning It is assumed that the value provided in 'bit' is within the + * boundaries of the word-array 'vli'. + * @note The bit ordering layout assumed for vli is: {31, 30, ..., 0}, + * {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting + * of 4 uECC_word_t elements. + */ +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); + +/* + * @brief Computes result = product % mod, where product is 2N words long. + * @param result OUT -- product % mod + * @param mod IN -- module + * @param num_words IN -- number of words + * @warning Currently only designed to work for curve_p or curve_n. + */ +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, + const uECC_word_t *mod, wordcount_t num_words); + +/* + * @brief Computes modular product (using curve->mmod_fast) + * @param result OUT -- (left * right) mod % curve_p + * @param left IN -- left term in product + * @param right IN -- right term in product + * @param curve IN -- elliptic curve + */ +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, uECC_Curve curve); + +/* + * @brief Computes result = left - right. + * @note Can modify in place. + * @param result OUT -- left - right + * @param left IN -- left term in subtraction + * @param right IN -- right term in subtraction + * @param num_words IN -- number of words + * @return borrow + */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words); + +/* + * @brief Constant-time comparison function(secure way to compare long ints) + * @param left IN -- left term in comparison + * @param right IN -- right term in comparison + * @param num_words IN -- number of words + * @return Returns 0 if left == right, 1 otherwise. + */ +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words); + +/* + * @brief Computes (left * right) % mod + * @param result OUT -- (left * right) % mod + * @param left IN -- left term in product + * @param right IN -- right term in product + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Computes (1 / input) % mod + * @note All VLIs are the same size. + * @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide" + * @param result OUT -- (1 / input) % mod + * @param input IN -- value to be modular inverted + * @param mod IN -- mod + * @param num_words -- number of words + */ +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, + const uECC_word_t *mod, wordcount_t num_words); + +/* + * @brief Sets dest = src. + * @param dest OUT -- destination buffer + * @param src IN -- origin buffer + * @param num_words IN -- number of words + */ +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, + wordcount_t num_words); + +/* + * @brief Computes (left + right) % mod. + * @note Assumes that (left < mod) and right < mod), and that result does not + * overlap mod. + * @param result OUT -- (left + right) % mod. + * @param left IN -- left term in addition + * @param right IN -- right term in addition + * @param mod IN -- mod + * @param num_words IN -- number of words + */ +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words); + +/* + * @brief Counts the number of bits required to represent vli. + * @param vli IN -- very long integer + * @param max_words IN -- number of words + * @return number of bits in given vli + */ +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, + const wordcount_t max_words); + +/* + * @brief Erases (set to 0) vli + * @param vli IN -- very long integer + * @param num_words IN -- number of words + */ +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); + +/* + * @brief check if it is a valid point in the curve + * @param point IN -- point to be checked + * @param curve IN -- elliptic curve + * @return 0 if point is valid + * @exception returns -1 if it is a point at infinity + * @exception returns -2 if x or y is smaller than p, + * @exception returns -3 if y^2 != x^3 + ax + b. + */ +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); + +/* + * @brief Check if a public key is valid. + * @param public_key IN -- The public key to be checked. + * @return returns 0 if the public key is valid + * @exception returns -1 if it is a point at infinity + * @exception returns -2 if x or y is smaller than p, + * @exception returns -3 if y^2 != x^3 + ax + b. + * @exception returns -4 if public key is the group generator. + * + * @note Note that you are not required to check for a valid public key before + * using any other uECC functions. However, you may wish to avoid spending CPU + * time computing a shared secret or verifying a signature using an invalid + * public key. + */ +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); + + /* + * @brief Converts an integer in uECC native format to big-endian bytes. + * @param bytes OUT -- bytes representation + * @param num_bytes IN -- number of bytes + * @param native IN -- uECC native representation + */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, + const unsigned int *native); + +/* + * @brief Converts big-endian bytes to an integer in uECC native format. + * @param native OUT -- uECC native representation + * @param bytes IN -- bytes representation + * @param num_bytes IN -- number of bytes + */ +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, + int num_bytes); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_UECC_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h index 1c88726785..b828e195db 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h @@ -1,135 +1,131 @@ -/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to EC-DH implementation. - * - * Overview: This software is an implementation of EC-DH. This implementation - * uses curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - */ - -#ifndef __TC_ECC_DH_H__ -#define __TC_ECC_DH_H__ - -#include "tinycrypt/ecc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Create a public/private key pair. - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - * - * @param p_public_key OUT -- Will be filled in with the public key. Must be at - * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key - * must be 64 bytes long. - * @param p_private_key OUT -- Will be filled in with the private key. Must be - * as long as the curve order (for secp256r1, p_private_key must be 32 bytes - * long). - * - * @note side-channel countermeasure: algorithm strengthened against timing - * attack. - * @warning A cryptographically-secure PRNG function must be set (using - * uECC_set_rng()) before calling uECC_make_key(). - */ -int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key); - -#ifdef ENABLE_TESTS - -/** - * @brief Create a public/private key pair given a specific d. - * - * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to - * uECC_make_key() function for real applications. - */ -int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, - unsigned int *d); -#endif - -/** - * @brief Compute a shared secret given your secret key and someone else's - * public key. - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - * - * @param p_secret OUT -- Will be filled in with the shared secret value. Must - * be the same size as the curve size (for curve secp256r1, secret must be 32 - * bytes long. - * @param p_public_key IN -- The public key of the remote party. - * @param p_private_key IN -- Your private key. - * - * @warning It is recommended to use the output of uECC_shared_secret() as the - * input of a recommended Key Derivation Function (see NIST SP 800-108) in - * order to produce a cryptographically secure symmetric key. - */ -int uECC_shared_secret(const uint8_t *p_public_key, - const uint8_t *p_private_key, uint8_t *p_secret); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_ECC_DH_H__ */ +/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to EC-DH implementation. + * + * Overview: This software is an implementation of EC-DH. This implementation + * uses curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + */ + +#ifndef __TC_ECC_DH_H__ +#define __TC_ECC_DH_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create a public/private key pair. + * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully + * returns TC_CRYPTO_FAIL (0) if error while generating key pair + * + * @param p_public_key OUT -- Will be filled in with the public key. Must be at + * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key + * must be 64 bytes long. + * @param p_private_key OUT -- Will be filled in with the private key. Must be as + * long as the curve order (for secp256r1, p_private_key must be 32 bytes long). + * + * @note side-channel countermeasure: algorithm strengthened against timing + * attack. + * @warning A cryptographically-secure PRNG function must be set (using + * uECC_set_rng()) before calling uECC_make_key(). + */ +int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve); + +#ifdef ENABLE_TESTS + +/** + * @brief Create a public/private key pair given a specific d. + * + * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to + * uECC_make_key() function for real applications. + */ +int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, + unsigned int *d, uECC_Curve curve); +#endif + +/** + * @brief Compute a shared secret given your secret key and someone else's + * public key. + * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully + * returns TC_CRYPTO_FAIL (0) otherwise + * + * @param p_secret OUT -- Will be filled in with the shared secret value. Must be + * the same size as the curve size (for curve secp256r1, secret must be 32 bytes + * long. + * @param p_public_key IN -- The public key of the remote party. + * @param p_private_key IN -- Your private key. + * + * @warning It is recommended to use the output of uECC_shared_secret() as the + * input of a recommended Key Derivation Function (see NIST SP 800-108) in + * order to produce a cryptographically secure symmetric key. + */ +int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key, + uint8_t *p_secret, uECC_Curve curve); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_ECC_DH_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h index 836c15bbb6..aca00bc95e 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h @@ -1,144 +1,139 @@ -/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to EC-DSA implementation. - * - * Overview: This software is an implementation of EC-DSA. This implementation - * uses curve NIST p-256. - * - * Security: The curve NIST p-256 provides approximately 128 bits of security. - * - * Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is - * recommended) and pass it in to ecdsa_sign function along with your - * private key and a random number. You must use a new non-predictable - * random number to generate each new signature. - * - To verify a signature: Compute the hash of the signed data using - * the same hash as the signer and pass it to this function along with - * the signer's public key and the signature values (r and s). - */ - -#ifndef __TC_ECC_DSA_H__ -#define __TC_ECC_DSA_H__ - -#include "tinycrypt/ecc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Generate an ECDSA signature for a given hash value. - * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED - * - * @param p_private_key IN -- Your private key. - * @param p_message_hash IN -- The hash of the message to sign. - * @param p_hash_size IN -- The size of p_message_hash in bytes. - * @param p_signature OUT -- Will be filled in with the signature value. Must be - * at least 2 * curve size long (for secp256r1, signature must be 64 bytes - * long). - * - * @warning A cryptographically-secure PRNG function must be set (using - * uECC_set_rng()) before calling uECC_sign(). - * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is - * recommended) and pass it in to this function along with your private key. - * @note side-channel countermeasure: algorithm strengthened against timing - * attack. - */ -int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, - unsigned p_hash_size, uint8_t *p_signature); - -#ifdef ENABLE_TESTS -/* - * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY. - * Refer to uECC_sign() function for real applications. - */ -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned int hash_size, uECC_word_t *k, - uint8_t *signature); -#endif - -/** - * @brief Verify an ECDSA signature. - * @return returns UECC_SUCCESS if the signature is valid - * returns UECC_FAILURE if the signature is invalid. - * - * @param p_public_key IN -- The signer's public key. - * @param p_message_hash IN -- The hash of the signed data. - * @param p_hash_size IN -- The size of p_message_hash in bytes. - * @param p_signature IN -- The signature values. - * - * @note Usage: Compute the hash of the signed data using the same hash as the - * signer and pass it to this function along with the signer's public key and - * the signature values (hash_size and signature). - */ -int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash, - unsigned int p_hash_size, const uint8_t *p_signature); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_ECC_DSA_H__ */ +/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief -- Interface to EC-DSA implementation. + * + * Overview: This software is an implementation of EC-DSA. This implementation + * uses curve NIST p-256. + * + * Security: The curve NIST p-256 provides approximately 128 bits of security. + * + * Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is + * recommended) and pass it in to ecdsa_sign function along with your + * private key and a random number. You must use a new non-predictable + * random number to generate each new signature. + * - To verify a signature: Compute the hash of the signed data using + * the same hash as the signer and pass it to this function along with + * the signer's public key and the signature values (r and s). + */ + +#ifndef __TC_ECC_DSA_H__ +#define __TC_ECC_DSA_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Generate an ECDSA signature for a given hash value. + * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully + * returns TC_CRYPTO_FAIL (0) if an error occurred. + * + * @param p_private_key IN -- Your private key. + * @param p_message_hash IN -- The hash of the message to sign. + * @param p_hash_size IN -- The size of p_message_hash in bytes. + * @param p_signature OUT -- Will be filled in with the signature value. Must be + * at least 2 * curve size long (for secp256r1, signature must be 64 bytes long). + * + * @warning A cryptographically-secure PRNG function must be set (using + * uECC_set_rng()) before calling uECC_sign(). + * @note Usage: Compute a hash of the data you wish to sign (SHA-2 is + * recommended) and pass it in to this function along with your private key. + * @note side-channel countermeasure: algorithm strengthened against timing + * attack. + */ +int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, + unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve); + +#ifdef ENABLE_TESTS +/* + * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY. + * Refer to uECC_sign() function for real applications. + */ +int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, + unsigned int hash_size, uECC_word_t *k, uint8_t *signature, + uECC_Curve curve); +#endif + +/** + * @brief Verify an ECDSA signature. + * @return returns TC_SUCCESS (1) if the signature is valid + * returns TC_FAIL (0) if the signature is invalid. + * + * @param p_public_key IN -- The signer's public key. + * @param p_message_hash IN -- The hash of the signed data. + * @param p_hash_size IN -- The size of p_message_hash in bytes. + * @param p_signature IN -- The signature values. + * + * @note Usage: Compute the hash of the signed data using the same hash as the + * signer and pass it to this function along with the signer's public key and + * the signature values (hash_size and signature). + */ +int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash, + unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_ECC_DSA_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h new file mode 100644 index 0000000000..e2c882356e --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h @@ -0,0 +1,81 @@ +/* uECC_platform_specific.h - Interface to platform specific functions*/ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * uECC_platform_specific.h -- Interface to platform specific functions + */ + +#ifndef __UECC_PLATFORM_SPECIFIC_H_ +#define __UECC_PLATFORM_SPECIFIC_H_ + +/* + * The RNG function should fill 'size' random bytes into 'dest'. It should + * return 1 if 'dest' was filled with random data, or 0 if the random data could + * not be generated. The filled-in values should be either truly random, or from + * a cryptographically-secure PRNG. + * + * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) + * before calling uECC_make_key() or uECC_sign(). + * + * Setting a cryptographically-secure PRNG function improves the resistance to + * side-channel attacks for uECC_shared_secret(). + * + * A correct PRNG function is set by default (default_RNG_defined = 1) and works + * for some platforms, such as Unix and Linux. For other platforms, you may need + * to provide another PRNG function. +*/ +#define default_RNG_defined 1 + +int default_CSPRNG(uint8_t *dest, unsigned int size); + +#endif /* __UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h new file mode 100644 index 0000000000..3a081494a8 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h @@ -0,0 +1,139 @@ +/* hmac.h - TinyCrypt interface to an HMAC implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to an HMAC implementation. + * + * Overview: HMAC is a message authentication code based on hash functions. + * TinyCrypt hard codes SHA-256 as the hash function. A message + * authentication code based on hash functions is also called a + * keyed cryptographic hash function since it performs a + * transformation specified by a key in an arbitrary length data + * set into a fixed length data set (also called tag). + * + * Security: The security of the HMAC depends on the length of the key and + * on the security of the hash function. Note that HMAC primitives + * are much less affected by collision attacks than their + * corresponding hash functions. + * + * Requires: SHA-256 + * + * Usage: 1) call tc_hmac_set_key to set the HMAC key. + * + * 2) call tc_hmac_init to initialize a struct hash_state before + * processing the data. + * + * 3) call tc_hmac_update to process the next input segment; + * tc_hmac_update can be called as many times as needed to process + * all of the segments of the input; the order is important. + * + * 4) call tc_hmac_final to out put the tag. + */ + +#ifndef __TC_HMAC_H__ +#define __TC_HMAC_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct tc_hmac_state_struct { + /* the internal state required by h */ + struct tc_sha256_state_struct hash_state; + /* HMAC key schedule */ + uint8_t key[2*TC_SHA256_BLOCK_SIZE]; +}; +typedef struct tc_hmac_state_struct *TCHmacState_t; + +/** + * @brief HMAC set key procedure + * Configures ctx to use key + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if + * ctx == NULL or + * key == NULL or + * key_size == 0 + * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial + * @param key IN -- the HMAC key to configure + * @param key_size IN -- the HMAC key size + */ +int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, + unsigned int key_size); + +/** + * @brief HMAC init procedure + * Initializes ctx to begin the next HMAC operation + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL + * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init + */ +int tc_hmac_init(TCHmacState_t ctx); + +/** + * @brief HMAC update procedure + * Mixes data_length bytes addressed by data into state + * @return returns TC_CRYPTO_SUCCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL + * @note Assumes state has been initialized by tc_hmac_init + * @param ctx IN/OUT -- state of HMAC computation so far + * @param data IN -- data to incorporate into state + * @param data_length IN -- size of data in bytes + */ +int tc_hmac_update(TCHmacState_t ctx, const void *data, + unsigned int data_length); + +/** + * @brief HMAC final procedure + * Writes the HMAC tag into the tag buffer + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * tag == NULL or + * ctx == NULL or + * key == NULL or + * taglen != TC_SHA256_DIGEST_SIZE + * @note ctx is erased before exiting. This should never be changed/removed. + * @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes + * state has been initialized by tc_hmac_init + * @param tag IN/OUT -- buffer to receive computed HMAC tag + * @param taglen IN -- size of tag in bytes + * @param ctx IN/OUT -- the HMAC state for computing tag + */ +int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx); + +#ifdef __cplusplus +} +#endif + +#endif /*__TC_HMAC_H__*/ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h new file mode 100644 index 0000000000..ad12cbbf0f --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h @@ -0,0 +1,164 @@ +/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to an HMAC-PRNG implementation. + * + * Overview: A pseudo-random number generator (PRNG) generates a sequence + * of numbers that have a distribution close to the one expected + * for a sequence of truly random numbers. The NIST Special + * Publication 800-90A specifies several mechanisms to generate + * sequences of pseudo random numbers, including the HMAC-PRNG one + * which is based on HMAC. TinyCrypt implements HMAC-PRNG with + * certain modifications from the NIST SP 800-90A spec. + * + * Security: A cryptographically secure PRNG depends on the existence of an + * entropy source to provide a truly random seed as well as the + * security of the primitives used as the building blocks (HMAC and + * SHA256, for TinyCrypt). + * + * The NIST SP 800-90A standard tolerates a null personalization, + * while TinyCrypt requires a non-null personalization. This is + * because a personalization string (the host name concatenated + * with a time stamp, for example) is easily computed and might be + * the last line of defense against failure of the entropy source. + * + * Requires: - SHA-256 + * - HMAC + * + * Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the + * personalization data. + * + * 2) call tc_hmac_prng_reseed to process the seed and additional + * input. + * + * 3) call tc_hmac_prng_generate to out put the pseudo-random data. + */ + +#ifndef __TC_HMAC_PRNG_H__ +#define __TC_HMAC_PRNG_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TC_HMAC_PRNG_RESEED_REQ -1 + +struct tc_hmac_prng_struct { + /* the HMAC instance for this PRNG */ + struct tc_hmac_state_struct h; + /* the PRNG key */ + uint8_t key[TC_SHA256_DIGEST_SIZE]; + /* PRNG state */ + uint8_t v[TC_SHA256_DIGEST_SIZE]; + /* calls to tc_hmac_prng_generate left before re-seed */ + unsigned int countdown; +}; + +typedef struct tc_hmac_prng_struct *TCHmacPrng_t; + +/** + * @brief HMAC-PRNG initialization procedure + * Initializes prng with personalization, disables tc_hmac_prng_generate + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * prng == NULL, + * personalization == NULL, + * plen > MAX_PLEN + * @note Assumes: - personalization != NULL. + * The personalization is a platform unique string (e.g., the host + * name) and is the last line of defense against failure of the + * entropy source + * @warning NIST SP 800-90A specifies 3 items as seed material during + * initialization: entropy seed, personalization, and an optional + * nonce. TinyCrypts requires instead a non-null personalization + * (which is easily computed) and indirectly requires an entropy + * seed (since the reseed function is mandatorily called after + * init) + * @param prng IN/OUT -- the PRNG state to initialize + * @param personalization IN -- personalization string + * @param plen IN -- personalization length in bytes + */ +int tc_hmac_prng_init(TCHmacPrng_t prng, + const uint8_t *personalization, + unsigned int plen); + +/** + * @brief HMAC-PRNG reseed procedure + * Mixes seed into prng, enables tc_hmac_prng_generate + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * prng == NULL, + * seed == NULL, + * seedlen < MIN_SLEN, + * seendlen > MAX_SLEN, + * additional_input != (const uint8_t *) 0 && additionallen == 0, + * additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN + * @note Assumes:- tc_hmac_prng_init has been called for prng + * - seed has sufficient entropy. + * + * @param prng IN/OUT -- the PRNG state + * @param seed IN -- entropy to mix into the prng + * @param seedlen IN -- length of seed in bytes + * @param additional_input IN -- additional input to the prng + * @param additionallen IN -- additional input length in bytes + */ +int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed, + unsigned int seedlen, const uint8_t *additional_input, + unsigned int additionallen); + +/** + * @brief HMAC-PRNG generate procedure + * Generates outlen pseudo-random bytes into out buffer, updates prng + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed + * returns TC_CRYPTO_FAIL (0) if: + * out == NULL, + * prng == NULL, + * outlen == 0, + * outlen >= MAX_OUT + * @note Assumes tc_hmac_prng_init has been called for prng + * @param out IN/OUT -- buffer to receive output + * @param outlen IN -- size of out buffer in bytes + * @param prng IN/OUT -- the PRNG state + */ +int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_HMAC_PRNG_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h new file mode 100644 index 0000000000..af5e8baf79 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h @@ -0,0 +1,129 @@ +/* sha256.h - TinyCrypt interface to a SHA-256 implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to a SHA-256 implementation. + * + * Overview: SHA-256 is a NIST approved cryptographic hashing algorithm + * specified in FIPS 180. A hash algorithm maps data of arbitrary + * size to data of fixed length. + * + * Security: SHA-256 provides 128 bits of security against collision attacks + * and 256 bits of security against pre-image attacks. SHA-256 does + * NOT behave like a random oracle, but it can be used as one if + * the string being hashed is prefix-free encoded before hashing. + * + * Usage: 1) call tc_sha256_init to initialize a struct + * tc_sha256_state_struct before hashing a new string. + * + * 2) call tc_sha256_update to hash the next string segment; + * tc_sha256_update can be called as many times as needed to hash + * all of the segments of a string; the order is important. + * + * 3) call tc_sha256_final to out put the digest from a hashing + * operation. + */ + +#ifndef __TC_SHA256_H__ +#define __TC_SHA256_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define TC_SHA256_BLOCK_SIZE (64) +#define TC_SHA256_DIGEST_SIZE (32) +#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4) + +struct tc_sha256_state_struct { + unsigned int iv[TC_SHA256_STATE_BLOCKS]; + uint64_t bits_hashed; + uint8_t leftover[TC_SHA256_BLOCK_SIZE]; + size_t leftover_offset; +}; + +typedef struct tc_sha256_state_struct *TCSha256State_t; + +/** + * @brief SHA256 initialization procedure + * Initializes s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if s == NULL + * @param s Sha256 state struct + */ +int tc_sha256_init(TCSha256State_t s); + +/** + * @brief SHA256 update procedure + * Hashes data_length bytes addressed by data into state s + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL, + * s->iv == NULL, + * data == NULL + * @note Assumes s has been initialized by tc_sha256_init + * @warning The state buffer 'leftover' is left in memory after processing + * If your application intends to have sensitive data in this + * buffer, remind to erase it after the data has been processed + * @param s Sha256 state struct + * @param data message to hash + * @param datalen length of message to hash + */ +int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen); + +/** + * @brief SHA256 final procedure + * Inserts the completed hash computation into digest + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * s == NULL, + * s->iv == NULL, + * digest == NULL + * @note Assumes: s has been initialized by tc_sha256_init + * digest points to at least TC_SHA256_DIGEST_SIZE bytes + * @warning The state buffer 'leftover' is left in memory after processing + * If your application intends to have sensitive data in this + * buffer, remind to erase it after the data has been processed + * @param digest unsigned eight bit integer + * @param Sha256 state struct + */ +int tc_sha256_final(uint8_t *digest, TCSha256State_t s); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_SHA256_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h new file mode 100644 index 0000000000..6b7b0abf9b --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h @@ -0,0 +1,121 @@ +/* utils.h - TinyCrypt interface to platform-dependent run-time operations */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief Interface to platform-dependent run-time operations. + * + */ + +#ifndef __TC_UTILS_H__ +#define __TC_UTILS_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Copy the the buffer 'from' to the buffer 'to'. + * @return returns TC_CRYPTO_SUCCESS (1) + * returns TC_CRYPTO_FAIL (0) if: + * from_len > to_len. + * + * @param to OUT -- destination buffer + * @param to_len IN -- length of destination buffer + * @param from IN -- origin buffer + * @param from_len IN -- length of origin buffer + */ +unsigned int _copy(uint8_t *to, unsigned int to_len, + const uint8_t *from, unsigned int from_len); + +/** + * @brief Set the value 'val' into the buffer 'to', 'len' times. + * + * @param to OUT -- destination buffer + * @param val IN -- value to be set in 'to' + * @param len IN -- number of times the value will be copied + */ +void _set(void *to, uint8_t val, unsigned int len); + +/** + * @brief Set the value 'val' into the buffer 'to', 'len' times, in a way + * which does not risk getting optimized out by the compiler + * In cases where the compiler does not set __GNUC__ and where the + * optimization level removes the memset, it may be necessary to + * implement a _set_secure function and define the + * TINYCRYPT_ARCH_HAS_SET_SECURE, which then can ensure that the + * memset does not get optimized out. + * + * @param to OUT -- destination buffer + * @param val IN -- value to be set in 'to' + * @param len IN -- number of times the value will be copied + */ +#ifdef TINYCRYPT_ARCH_HAS_SET_SECURE +extern void _set_secure(void *to, uint8_t val, unsigned int len); +#else /* ! TINYCRYPT_ARCH_HAS_SET_SECURE */ +static inline void _set_secure(void *to, uint8_t val, unsigned int len) +{ + (void) memset(to, val, len); +#ifdef __GNUC__ + __asm__ __volatile__("" :: "g"(to) : "memory"); +#endif /* __GNUC__ */ +} +#endif /* TINYCRYPT_ARCH_HAS_SET_SECURE */ + +/* + * @brief AES specific doubling function, which utilizes + * the finite field used by AES. + * @return Returns a^2 + * + * @param a IN/OUT -- value to be doubled + */ +uint8_t _double_byte(uint8_t a); + +/* + * @brief Constant-time algorithm to compare if two sequences of bytes are equal + * @return Returns 0 if equal, and non-zero otherwise + * + * @param a IN -- sequence of bytes a + * @param b IN -- sequence of bytes b + * @param size IN -- size of sequences a and b + */ +int _compare(const uint8_t *a, const uint8_t *b, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* __TC_UTILS_H__ */ diff --git a/matter/mbedtls/tinycrypt/src/aes_decrypt.c b/matter/mbedtls/tinycrypt/src/aes_decrypt.c new file mode 100644 index 0000000000..993a6180ce --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/aes_decrypt.c @@ -0,0 +1,164 @@ +/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static const uint8_t inv_sbox[256] = { + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d +}; + +int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k) +{ + return tc_aes128_set_encrypt_key(s, k); +} + +#define mult8(a)(_double_byte(_double_byte(_double_byte(a)))) +#define mult9(a)(mult8(a)^(a)) +#define multb(a)(mult8(a)^_double_byte(a)^(a)) +#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a)) +#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a)) + +static inline void mult_row_column(uint8_t *out, const uint8_t *in) +{ + out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]); + out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]); + out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]); + out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]); +} + +static inline void inv_mix_columns(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + mult_row_column(t, s); + mult_row_column(&t[Nb], s+Nb); + mult_row_column(&t[2*Nb], s+(2*Nb)); + mult_row_column(&t[3*Nb], s+(3*Nb)); + (void)_copy(s, sizeof(t), t, sizeof(t)); +} + +static inline void add_round_key(uint8_t *s, const unsigned int *k) +{ + s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); + s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); + s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); + s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); + s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); + s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); + s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); + s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); +} + +static inline void inv_sub_bytes(uint8_t *s) +{ + unsigned int i; + + for (i = 0; i < (Nb*Nk); ++i) { + s[i] = inv_sbox[s[i]]; + } +} + +/* + * This inv_shift_rows also implements the matrix flip required for + * inv_mix_columns, but performs it here to reduce the number of memory + * operations. + */ +static inline void inv_shift_rows(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7]; + t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11]; + t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15]; + t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3]; + (void)_copy(s, sizeof(t), t, sizeof(t)); +} + +int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) +{ + uint8_t state[Nk*Nb]; + unsigned int i; + + if (out == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (in == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)_copy(state, sizeof(state), in, sizeof(state)); + + add_round_key(state, s->words + Nb*Nr); + + for (i = Nr - 1; i > 0; --i) { + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, s->words + Nb*i); + inv_mix_columns(state); + } + + inv_shift_rows(state); + inv_sub_bytes(state); + add_round_key(state, s->words); + + (void)_copy(out, sizeof(state), state, sizeof(state)); + + /*zeroing out the state buffer */ + _set(state, TC_ZERO_BYTE, sizeof(state)); + + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/aes_encrypt.c b/matter/mbedtls/tinycrypt/src/aes_encrypt.c new file mode 100644 index 0000000000..8991aee522 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/aes_encrypt.c @@ -0,0 +1,191 @@ +/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static const uint8_t sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16 +}; + +static inline unsigned int rotword(unsigned int a) +{ + return (((a) >> 24)|((a) << 8)); +} + +#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o)) +#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0)) + +int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k) +{ + const unsigned int rconst[11] = { + 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, + 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 + }; + unsigned int i; + unsigned int t; + + if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } else if (k == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + for (i = 0; i < Nk; ++i) { + s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) | + (k[Nb*i+2]<<8) | (k[Nb*i+3]); + } + + for (; i < (Nb * (Nr + 1)); ++i) { + t = s->words[i-1]; + if ((i % Nk) == 0) { + t = subword(rotword(t)) ^ rconst[i/Nk]; + } + s->words[i] = s->words[i-Nk] ^ t; + } + + return TC_CRYPTO_SUCCESS; +} + +static inline void add_round_key(uint8_t *s, const unsigned int *k) +{ + s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); + s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); + s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); + s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); + s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); + s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); + s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); + s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); +} + +static inline void sub_bytes(uint8_t *s) +{ + unsigned int i; + + for (i = 0; i < (Nb * Nk); ++i) { + s[i] = sbox[s[i]]; + } +} + +#define triple(a)(_double_byte(a)^(a)) + +static inline void mult_row_column(uint8_t *out, const uint8_t *in) +{ + out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3]; + out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3]; + out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]); + out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]); +} + +static inline void mix_columns(uint8_t *s) +{ + uint8_t t[Nb*Nk]; + + mult_row_column(t, s); + mult_row_column(&t[Nb], s+Nb); + mult_row_column(&t[2 * Nb], s + (2 * Nb)); + mult_row_column(&t[3 * Nb], s + (3 * Nb)); + (void) _copy(s, sizeof(t), t, sizeof(t)); +} + +/* + * This shift_rows also implements the matrix flip required for mix_columns, but + * performs it here to reduce the number of memory operations. + */ +static inline void shift_rows(uint8_t *s) +{ + uint8_t t[Nb * Nk]; + + t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15]; + t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3]; + t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7]; + t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11]; + (void) _copy(s, sizeof(t), t, sizeof(t)); +} + +int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) +{ + uint8_t state[Nk*Nb]; + unsigned int i; + + if (out == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (in == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (s == (TCAesKeySched_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)_copy(state, sizeof(state), in, sizeof(state)); + add_round_key(state, s->words); + + for (i = 0; i < (Nr - 1); ++i) { + sub_bytes(state); + shift_rows(state); + mix_columns(state); + add_round_key(state, s->words + Nb*(i+1)); + } + + sub_bytes(state); + shift_rows(state); + add_round_key(state, s->words + Nb*(i+1)); + + (void)_copy(out, sizeof(state), state, sizeof(state)); + + /* zeroing out the state buffer */ + _set(state, TC_ZERO_BYTE, sizeof(state)); + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/cbc_mode.c b/matter/mbedtls/tinycrypt/src/cbc_mode.c new file mode 100644 index 0000000000..ae20af1a70 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/cbc_mode.c @@ -0,0 +1,114 @@ +/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + unsigned int n, m; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (const uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + (inlen % TC_AES_BLOCK_SIZE) != 0 || + (outlen % TC_AES_BLOCK_SIZE) != 0 || + outlen != inlen + TC_AES_BLOCK_SIZE) { + return TC_CRYPTO_FAIL; + } + + /* copy iv to the buffer */ + (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); + /* copy iv to the output buffer */ + (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); + out += TC_AES_BLOCK_SIZE; + + for (n = m = 0; n < inlen; ++n) { + buffer[m++] ^= *in++; + if (m == TC_AES_BLOCK_SIZE) { + (void)tc_aes_encrypt(buffer, buffer, sched); + (void)_copy(out, TC_AES_BLOCK_SIZE, + buffer, TC_AES_BLOCK_SIZE); + out += TC_AES_BLOCK_SIZE; + m = 0; + } + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, const uint8_t *iv, + const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + const uint8_t *p; + unsigned int n, m; + + /* sanity check the inputs */ + if (out == (uint8_t *) 0 || + in == (const uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + (inlen % TC_AES_BLOCK_SIZE) != 0 || + (outlen % TC_AES_BLOCK_SIZE) != 0 || + outlen != inlen) { + return TC_CRYPTO_FAIL; + } + + /* + * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are + * contiguous. This allows for a very efficient decryption algorithm + * that would not otherwise be possible. + */ + p = iv; + for (n = m = 0; n < outlen; ++n) { + if ((n % TC_AES_BLOCK_SIZE) == 0) { + (void)tc_aes_decrypt(buffer, in, sched); + in += TC_AES_BLOCK_SIZE; + m = 0; + } + *out++ = buffer[m++] ^ *p++; + } + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/ccm_mode.c b/matter/mbedtls/tinycrypt/src/ccm_mode.c new file mode 100644 index 0000000000..929adac630 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/ccm_mode.c @@ -0,0 +1,266 @@ +/* ccm_mode.c - TinyCrypt implementation of CCM mode */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, + unsigned int nlen, unsigned int mlen) +{ + + /* input sanity check: */ + if (c == (TCCcmMode_t) 0 || + sched == (TCAesKeySched_t) 0 || + nonce == (uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } else if (nlen != 13) { + return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/ + } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) { + return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/ + } + + c->mlen = mlen; + c->sched = sched; + c->nonce = nonce; + + return TC_CRYPTO_SUCCESS; +} + +/** + * Variation of CBC-MAC mode used in CCM. + */ +static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen, + unsigned int flag, TCAesKeySched_t sched) +{ + + unsigned int i; + + if (flag > 0) { + T[0] ^= (uint8_t)(dlen >> 8); + T[1] ^= (uint8_t)(dlen); + dlen += 2; i = 2; + } else { + i = 0; + } + + while (i < dlen) { + T[i++ % (Nb * Nk)] ^= *data++; + if (((i % (Nb * Nk)) == 0) || dlen == i) { + (void) tc_aes_encrypt(T, T, sched); + } + } +} + +/** + * Variation of CTR mode used in CCM. + * The CTR mode used by CCM is slightly different than the conventional CTR + * mode (the counter is increased before encryption, instead of after + * encryption). Besides, it is assumed that the counter is stored in the last + * 2 bytes of the nonce. + */ +static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + uint8_t nonce[TC_AES_BLOCK_SIZE]; + uint16_t block_num; + unsigned int i; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (uint8_t *) 0 || + ctr == (uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + outlen != inlen) { + return TC_CRYPTO_FAIL; + } + + /* copy the counter to the nonce */ + (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); + + /* select the last 2 bytes of the nonce to be incremented */ + block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15])); + for (i = 0; i < inlen; ++i) { + if ((i % (TC_AES_BLOCK_SIZE)) == 0) { + block_num++; + nonce[14] = (uint8_t)(block_num >> 8); + nonce[15] = (uint8_t)(block_num); + if (!tc_aes_encrypt(buffer, nonce, sched)) { + return TC_CRYPTO_FAIL; + } + } + /* update the output */ + *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++; + } + + /* update the counter */ + ctr[14] = nonce[14]; ctr[15] = nonce[15]; + + return TC_CRYPTO_SUCCESS; +} + +int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c) +{ + + /* input sanity check: */ + if ((out == (uint8_t *) 0) || + (c == (TCCcmMode_t) 0) || + ((plen > 0) && (payload == (uint8_t *) 0)) || + ((alen > 0) && (associated_data == (uint8_t *) 0)) || + (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ + (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ + (olen < (plen + c->mlen))) { /* invalid output buffer size */ + return TC_CRYPTO_FAIL; + } + + uint8_t b[Nb * Nk]; + uint8_t tag[Nb * Nk]; + unsigned int i; + + /* GENERATING THE AUTHENTICATION TAG: */ + + /* formatting the sequence b for authentication: */ + b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1); + for (i = 1; i <= 13; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = (uint8_t)(plen >> 8); + b[15] = (uint8_t)(plen); + + /* computing the authentication tag using cbc-mac: */ + (void) tc_aes_encrypt(tag, b, c->sched); + if (alen > 0) { + ccm_cbc_mac(tag, associated_data, alen, 1, c->sched); + } + if (plen > 0) { + ccm_cbc_mac(tag, payload, plen, 0, c->sched); + } + + /* ENCRYPTION: */ + + /* formatting the sequence b for encryption: */ + b[0] = 1; /* q - 1 = 2 - 1 = 1 */ + b[14] = b[15] = TC_ZERO_BYTE; + + /* encrypting payload using ctr mode: */ + ccm_ctr_mode(out, plen, payload, plen, b, c->sched); + + b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/ + + /* encrypting b and adding the tag to the output: */ + (void) tc_aes_encrypt(b, b, c->sched); + out += plen; + for (i = 0; i < c->mlen; ++i) { + *out++ = tag[i] ^ b[i]; + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, + const uint8_t *associated_data, + unsigned int alen, const uint8_t *payload, + unsigned int plen, TCCcmMode_t c) +{ + + /* input sanity check: */ + if ((out == (uint8_t *) 0) || + (c == (TCCcmMode_t) 0) || + ((plen > 0) && (payload == (uint8_t *) 0)) || + ((alen > 0) && (associated_data == (uint8_t *) 0)) || + (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ + (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ + (olen < plen - c->mlen)) { /* invalid output buffer size */ + return TC_CRYPTO_FAIL; + } + + uint8_t b[Nb * Nk]; + uint8_t tag[Nb * Nk]; + unsigned int i; + + /* DECRYPTION: */ + + /* formatting the sequence b for decryption: */ + b[0] = 1; /* q - 1 = 2 - 1 = 1 */ + for (i = 1; i < 14; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */ + + /* decrypting payload using ctr mode: */ + ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched); + + b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */ + + /* encrypting b and restoring the tag from input: */ + (void) tc_aes_encrypt(b, b, c->sched); + for (i = 0; i < c->mlen; ++i) { + tag[i] = *(payload + plen - c->mlen + i) ^ b[i]; + } + + /* VERIFYING THE AUTHENTICATION TAG: */ + + /* formatting the sequence b for authentication: */ + b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1); + for (i = 1; i < 14; ++i) { + b[i] = c->nonce[i - 1]; + } + b[14] = (uint8_t)((plen - c->mlen) >> 8); + b[15] = (uint8_t)(plen - c->mlen); + + /* computing the authentication tag using cbc-mac: */ + (void) tc_aes_encrypt(b, b, c->sched); + if (alen > 0) { + ccm_cbc_mac(b, associated_data, alen, 1, c->sched); + } + if (plen > 0) { + ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched); + } + + /* comparing the received tag and the computed one: */ + if (_compare(b, tag, c->mlen) == 0) { + return TC_CRYPTO_SUCCESS; + } else { + /* erase the decrypted buffer in case of mac validation failure: */ + _set(out, 0, plen - c->mlen); + return TC_CRYPTO_FAIL; + } +} diff --git a/matter/mbedtls/tinycrypt/src/cmac_mode.c b/matter/mbedtls/tinycrypt/src/cmac_mode.c new file mode 100644 index 0000000000..22adf2089f --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/cmac_mode.c @@ -0,0 +1,254 @@ +/* cmac_mode.c - TinyCrypt CMAC mode implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* max number of calls until change the key (2^48).*/ +static const uint64_t MAX_CALLS = ((uint64_t)1 << 48); + +/* + * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte + * array with byte 0 the most significant and byte 15 the least significant. + * High bit carry reduction is based on the primitive polynomial + * + * X^128 + X^7 + X^2 + X + 1, + * + * which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed, + * since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since + * addition of polynomials with coefficients in Z/Z(2) is just XOR, we can + * add X^128 to both sides to get + * + * X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1) + * + * and the coefficients of the polynomial on the right hand side form the + * string 1000 0111 = 0x87, which is the value of gf_wrap. + * + * This gets used in the following way. Doubling in GF(2^128) is just a left + * shift by 1 bit, except when the most significant bit is 1. In the latter + * case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit + * that overflows beyond 128 bits can be replaced by addition of + * X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition + * in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87 + * into the low order byte after a left shift when the starting high order + * bit is 1. + */ +const unsigned char gf_wrap = 0x87; + +/* + * assumes: out != NULL and points to a GF(2^n) value to receive the + * doubled value; + * in != NULL and points to a 16 byte GF(2^n) value + * to double; + * the in and out buffers do not overlap. + * effects: doubles the GF(2^n) value pointed to by "in" and places + * the result in the GF(2^n) value pointed to by "out." + */ +void gf_double(uint8_t *out, uint8_t *in) +{ + + /* start with low order byte */ + uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1); + + /* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */ + uint8_t carry = (in[0] >> 7) ? gf_wrap : 0; + + out += (TC_AES_BLOCK_SIZE - 1); + for (;;) { + *out-- = (*x << 1) ^ carry; + if (x == in) { + break; + } + carry = *x-- >> 7; + } +} + +int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched) +{ + + /* input sanity check: */ + if (s == (TCCmacState_t) 0 || + key == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + /* put s into a known state */ + _set(s, 0, sizeof(*s)); + s->sched = sched; + + /* configure the encryption key used by the underlying block cipher */ + tc_aes128_set_encrypt_key(s->sched, key); + + /* compute s->K1 and s->K2 from s->iv using s->keyid */ + _set(s->iv, 0, TC_AES_BLOCK_SIZE); + tc_aes_encrypt(s->iv, s->iv, s->sched); + gf_double (s->K1, s->iv); + gf_double (s->K2, s->K1); + + /* reset s->iv to 0 in case someone wants to compute now */ + tc_cmac_init(s); + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_erase(TCCmacState_t s) +{ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* destroy the current state */ + _set(s, 0, sizeof(*s)); + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_init(TCCmacState_t s) +{ + /* input sanity check: */ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* CMAC starts with an all zero initialization vector */ + _set(s->iv, 0, TC_AES_BLOCK_SIZE); + + /* and the leftover buffer is empty */ + _set(s->leftover, 0, TC_AES_BLOCK_SIZE); + s->leftover_offset = 0; + + /* Set countdown to max number of calls allowed before re-keying: */ + s->countdown = MAX_CALLS; + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length) +{ + unsigned int i; + + /* input sanity check: */ + if (s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + if (data_length == 0) { + return TC_CRYPTO_SUCCESS; + } + if (data == (const uint8_t *) 0) { + return TC_CRYPTO_FAIL; + } + + if (s->countdown == 0) { + return TC_CRYPTO_FAIL; + } + + s->countdown--; + + if (s->leftover_offset > 0) { + /* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */ + size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset; + + if (data_length < remaining_space) { + /* still not enough data to encrypt this time either */ + _copy(&s->leftover[s->leftover_offset], data_length, data, data_length); + s->leftover_offset += data_length; + return TC_CRYPTO_SUCCESS; + } + /* leftover block is now full; encrypt it first */ + _copy(&s->leftover[s->leftover_offset], + remaining_space, + data, + remaining_space); + data_length -= remaining_space; + data += remaining_space; + s->leftover_offset = 0; + + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= s->leftover[i]; + } + tc_aes_encrypt(s->iv, s->iv, s->sched); + } + + /* CBC encrypt each (except the last) of the data blocks */ + while (data_length > TC_AES_BLOCK_SIZE) { + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= data[i]; + } + tc_aes_encrypt(s->iv, s->iv, s->sched); + data += TC_AES_BLOCK_SIZE; + data_length -= TC_AES_BLOCK_SIZE; + } + + if (data_length > 0) { + /* save leftover data for next time */ + _copy(s->leftover, data_length, data, data_length); + s->leftover_offset = data_length; + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_cmac_final(uint8_t *tag, TCCmacState_t s) +{ + uint8_t *k; + unsigned int i; + + /* input sanity check: */ + if (tag == (uint8_t *) 0 || + s == (TCCmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + if (s->leftover_offset == TC_AES_BLOCK_SIZE) { + /* the last message block is a full-sized block */ + k = (uint8_t *) s->K1; + } else { + /* the final message block is not a full-sized block */ + size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset; + + _set(&s->leftover[s->leftover_offset], 0, remaining); + s->leftover[s->leftover_offset] = TC_CMAC_PADDING; + k = (uint8_t *) s->K2; + } + for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { + s->iv[i] ^= s->leftover[i] ^ k[i]; + } + + tc_aes_encrypt(tag, s->iv, s->sched); + + /* erasing state: */ + tc_cmac_erase(s); + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/ctr_mode.c b/matter/mbedtls/tinycrypt/src/ctr_mode.c new file mode 100644 index 0000000000..1dfb92dfec --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/ctr_mode.c @@ -0,0 +1,85 @@ +/* ctr_mode.c - TinyCrypt CTR mode implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, + unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) +{ + + uint8_t buffer[TC_AES_BLOCK_SIZE]; + uint8_t nonce[TC_AES_BLOCK_SIZE]; + unsigned int block_num; + unsigned int i; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + in == (uint8_t *) 0 || + ctr == (uint8_t *) 0 || + sched == (TCAesKeySched_t) 0 || + inlen == 0 || + outlen == 0 || + outlen != inlen) { + return TC_CRYPTO_FAIL; + } + + /* copy the ctr to the nonce */ + (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); + + /* select the last 4 bytes of the nonce to be incremented */ + block_num = (nonce[12] << 24) | (nonce[13] << 16) | + (nonce[14] << 8) | (nonce[15]); + for (i = 0; i < inlen; ++i) { + if ((i % (TC_AES_BLOCK_SIZE)) == 0) { + /* encrypt data using the current nonce */ + if (tc_aes_encrypt(buffer, nonce, sched)) { + block_num++; + nonce[12] = (uint8_t)(block_num >> 24); + nonce[13] = (uint8_t)(block_num >> 16); + nonce[14] = (uint8_t)(block_num >> 8); + nonce[15] = (uint8_t)(block_num); + } else { + return TC_CRYPTO_FAIL; + } + } + /* update the output */ + *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++; + } + + /* update the counter */ + ctr[12] = nonce[12]; ctr[13] = nonce[13]; + ctr[14] = nonce[14]; ctr[15] = nonce[15]; + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/ctr_prng.c b/matter/mbedtls/tinycrypt/src/ctr_prng.c new file mode 100644 index 0000000000..cac2cc41d6 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/ctr_prng.c @@ -0,0 +1,283 @@ +/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */ + +/* + * Copyright (c) 2016, Chris Morrison + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * This PRNG is based on the CTR_DRBG described in Recommendation for Random + * Number Generation Using Deterministic Random Bit Generators, + * NIST SP 800-90A Rev. 1. + * + * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps + * described in that document. + * + */ + +/** + * @brief Array incrementer + * Treats the supplied array as one contiguous number (MSB in arr[0]), and + * increments it by one + * @return none + * @param arr IN/OUT -- array to be incremented + * @param len IN -- size of arr in bytes + */ +static void arrInc(uint8_t arr[], unsigned int len) +{ + unsigned int i; + if (0 != arr) { + for (i = len; i > 0U; i--) { + if (++arr[i-1] != 0U) { + break; + } + } + } +} + +/** + * @brief CTR PRNG update + * Updates the internal state of supplied the CTR PRNG context + * increments it by one + * @return none + * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long + * @param ctx IN/OUT -- CTR PRNG state + * @param providedData IN -- data used when updating the internal state + */ +static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData) +{ + if (0 != ctx) { + /* 10.2.1.2 step 1 */ + uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + unsigned int len = 0U; + + /* 10.2.1.2 step 2 */ + while (len < sizeof temp) { + unsigned int blocklen = sizeof(temp) - len; + uint8_t output_block[TC_AES_BLOCK_SIZE]; + + /* 10.2.1.2 step 2.1 */ + arrInc(ctx->V, sizeof ctx->V); + + /* 10.2.1.2 step 2.2 */ + if (blocklen > TC_AES_BLOCK_SIZE) { + blocklen = TC_AES_BLOCK_SIZE; + } + (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); + + /* 10.2.1.2 step 2.3/step 3 */ + memcpy(&(temp[len]), output_block, blocklen); + + len += blocklen; + } + + /* 10.2.1.2 step 4 */ + if (0 != providedData) { + unsigned int i; + for (i = 0U; i < sizeof temp; i++) { + temp[i] ^= providedData[i]; + } + } + + /* 10.2.1.2 step 5 */ + (void)tc_aes128_set_encrypt_key(&ctx->key, temp); + + /* 10.2.1.2 step 6 */ + memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE); + } +} + +int tc_ctr_prng_init(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const personalization, + unsigned int pLen) +{ + int result = TC_CRYPTO_FAIL; + unsigned int i; + uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U}; + + if (0 != personalization) { + /* 10.2.1.3.1 step 1 */ + unsigned int len = pLen; + if (len > sizeof personalization_buf) { + len = sizeof personalization_buf; + } + + /* 10.2.1.3.1 step 2 */ + memcpy(personalization_buf, personalization, len); + } + + if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) { + /* 10.2.1.3.1 step 3 */ + memcpy(seed_material, entropy, sizeof seed_material); + for (i = 0U; i < sizeof seed_material; i++) { + seed_material[i] ^= personalization_buf[i]; + } + + /* 10.2.1.3.1 step 4 */ + (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr); + + /* 10.2.1.3.1 step 5 */ + memset(ctx->V, 0x00, sizeof ctx->V); + + /* 10.2.1.3.1 step 6 */ + tc_ctr_prng_update(ctx, seed_material); + + /* 10.2.1.3.1 step 7 */ + ctx->reseedCount = 1U; + + result = TC_CRYPTO_SUCCESS; + } + return result; +} + +int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, + uint8_t const * const entropy, + unsigned int entropyLen, + uint8_t const * const additional_input, + unsigned int additionallen) +{ + unsigned int i; + int result = TC_CRYPTO_FAIL; + uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; + + if (0 != additional_input) { + /* 10.2.1.4.1 step 1 */ + unsigned int len = additionallen; + if (len > sizeof additional_input_buf) { + len = sizeof additional_input_buf; + } + + /* 10.2.1.4.1 step 2 */ + memcpy(additional_input_buf, additional_input, len); + } + + unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE; + if ((0 != ctx) && (entropyLen >= seedlen)) { + /* 10.2.1.4.1 step 3 */ + memcpy(seed_material, entropy, sizeof seed_material); + for (i = 0U; i < sizeof seed_material; i++) { + seed_material[i] ^= additional_input_buf[i]; + } + + /* 10.2.1.4.1 step 4 */ + tc_ctr_prng_update(ctx, seed_material); + + /* 10.2.1.4.1 step 5 */ + ctx->reseedCount = 1U; + + result = TC_CRYPTO_SUCCESS; + } + return result; +} + +int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, + uint8_t const * const additional_input, + unsigned int additionallen, + uint8_t * const out, + unsigned int outlen) +{ + /* 2^48 - see section 10.2.1 */ + static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; + + /* 2^19 bits - see section 10.2.1 */ + static const unsigned int MAX_BYTES_PER_REQ = 65536U; + + unsigned int result = TC_CRYPTO_FAIL; + + if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) { + /* 10.2.1.5.1 step 1 */ + if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) { + result = TC_CTR_PRNG_RESEED_REQ; + } else { + uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; + if (0 != additional_input) { + /* 10.2.1.5.1 step 2 */ + unsigned int len = additionallen; + if (len > sizeof additional_input_buf) { + len = sizeof additional_input_buf; + } + memcpy(additional_input_buf, additional_input, len); + tc_ctr_prng_update(ctx, additional_input_buf); + } + + /* 10.2.1.5.1 step 3 - implicit */ + + /* 10.2.1.5.1 step 4 */ + unsigned int len = 0U; + while (len < outlen) { + unsigned int blocklen = outlen - len; + uint8_t output_block[TC_AES_BLOCK_SIZE]; + + /* 10.2.1.5.1 step 4.1 */ + arrInc(ctx->V, sizeof ctx->V); + + /* 10.2.1.5.1 step 4.2 */ + (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); + + /* 10.2.1.5.1 step 4.3/step 5 */ + if (blocklen > TC_AES_BLOCK_SIZE) { + blocklen = TC_AES_BLOCK_SIZE; + } + memcpy(&(out[len]), output_block, blocklen); + + len += blocklen; + } + + /* 10.2.1.5.1 step 6 */ + tc_ctr_prng_update(ctx, additional_input_buf); + + /* 10.2.1.5.1 step 7 */ + ctx->reseedCount++; + + /* 10.2.1.5.1 step 8 */ + result = TC_CRYPTO_SUCCESS; + } + } + + return result; +} + +void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx) +{ + if (0 != ctx) { + memset(ctx->key.words, 0x00, sizeof ctx->key.words); + memset(ctx->V, 0x00, sizeof ctx->V); + ctx->reseedCount = 0U; + } +} + + + + diff --git a/matter/mbedtls/tinycrypt/src/ecc.c b/matter/mbedtls/tinycrypt/src/ecc.c index 2ac5c535d3..46080bf619 100644 --- a/matter/mbedtls/tinycrypt/src/ecc.c +++ b/matter/mbedtls/tinycrypt/src/ecc.c @@ -1,1738 +1,942 @@ -/* ecc.c - TinyCrypt implementation of common ECC functions */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "mbedtls/platform_util.h" -#include "mbedtls/sha256.h" -#include "tinycrypt/ecc.h" -#include - -#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) -#include "platform_fault.h" -#else -static void mbedtls_platform_fault() {} -#endif - -#if defined OPTIMIZE_TINYCRYPT_ASM -#ifndef asm -#define asm __asm -#endif -#endif /* OPTIMIZE_TINYCRYPT_ASM */ - -/* Parameters for curve NIST P-256 aka secp256r1 */ -const uECC_word_t curve_p[NUM_ECC_WORDS] = { - TC_BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - TC_BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), - TC_BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), - TC_BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)}; -const uECC_word_t curve_n[NUM_ECC_WORDS] = { - TC_BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), - TC_BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), - TC_BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - TC_BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)}; -const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = { - TC_BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), - TC_BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), - TC_BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), - TC_BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), - TC_BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), - TC_BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), - TC_BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), - TC_BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)}; -const uECC_word_t curve_b[NUM_ECC_WORDS] = { - TC_BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), - TC_BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), - TC_BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), - TC_BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)}; - -static int uECC_update_param_sha256(mbedtls_sha256_context *ctx, - const uECC_word_t val[NUM_ECC_WORDS]) { - uint8_t bytes[NUM_ECC_BYTES]; - - uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val); - return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES); -} - -static int uECC_compute_param_sha256(unsigned char output[32]) { - int ret = UECC_FAILURE; - mbedtls_sha256_context ctx; - - mbedtls_sha256_init(&ctx); - - if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) { - goto exit; - } - - if (uECC_update_param_sha256(&ctx, curve_p) != 0 || - uECC_update_param_sha256(&ctx, curve_n) != 0 || - uECC_update_param_sha256(&ctx, curve_G) != 0 || - uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 || - uECC_update_param_sha256(&ctx, curve_b) != 0) { - goto exit; - } - - if (mbedtls_sha256_finish_ret(&ctx, output) != 0) { - goto exit; - } - - ret = UECC_SUCCESS; - -exit: - mbedtls_sha256_free(&ctx); - - return ret; -} - -/* - * Check integrity of curve parameters. - * Return 0 if everything's OK, non-zero otherwise. - */ -static int uECC_check_curve_integrity(void) { - unsigned char computed[32]; - static const unsigned char reference[32] = { - 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1, 0x93, 0xf9, 0x29, - 0x2f, 0xac, 0x3e, 0xe2, 0x92, 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, - 0xa2, 0xc6, 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49, - }; - int diff = 0; - unsigned char tmp1, tmp2; - volatile unsigned i; - - if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) { - return UECC_FAILURE; - } - - for (i = 0; i < 32; i++) { - /* make sure the order of volatile accesses is well-defined */ - tmp1 = computed[i]; - tmp2 = reference[i]; - diff |= tmp1 ^ tmp2; - } - - /* i should be 32 */ - mbedtls_platform_random_delay(); - diff |= i ^ 32; - - return diff; -} - -/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform - * has access to enough entropy in order to feed the PRNG regularly. */ -#if default_RNG_defined -static uECC_RNG_Function g_rng_function = &default_CSPRNG; -#else -static uECC_RNG_Function g_rng_function = 0; -#endif - -void uECC_set_rng(uECC_RNG_Function rng_function) { - g_rng_function = rng_function; -} - -uECC_RNG_Function uECC_get_rng(void) { return g_rng_function; } - -int uECC_curve_private_key_size(void) { return TC_BITS_TO_BYTES(NUM_ECC_BITS); } - -int uECC_curve_public_key_size(void) { return 2 * NUM_ECC_BYTES; } - -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -__asm void uECC_vli_clear(uECC_word_t *vli) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4 - MOVS r1, #0 MOVS r2, #0 STMIA r0 !, {r1, r2} STMIA r0 !, {r1, r2} STMIA r0 !, - {r1, r2} STMIA r0 !, {r1, r2} BX lr -#else - MOVS r1, #0 STRD r1, r1, - [ r0, #0 ] // Only Thumb2 STRD can store same reg twice, not ARM - STRD r1, - r1, [ r0, #8 ] STRD r1, r1, [ r0, #16 ] STRD r1, r1, [ r0, #24 ] BX lr -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -void uECC_vli_clear(uECC_word_t *vli) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if !defined __thumb__ || !defined __thumb2__ - register uECC_word_t *r0 asm("r0") = vli; - register uECC_word_t r1 asm("r1") = 0; - register uECC_word_t r2 asm("r2") = 0; - asm volatile(".syntax unified \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - ".syntax divided \n\t" - : "+r"(r0) - : "r"(r1), "r"(r2) - : "memory" -#else - register uECC_word_t *r0 asm("r0") = vli; - register uECC_word_t r1 asm("r1") = 0; - asm volatile("STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store - // same reg twice, not ARM - "STRD r1,r1,[r0,#8] \n\t" - "STRD r1,r1,[r0,#16] \n\t" - "STRD r1,r1,[r0,#24] \n\t" - : - : "r"(r0), "r"(r1) - : "memory" -#endif - ); -} -#else -void uECC_vli_clear(uECC_word_t *vli) { - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - vli[i] = 0; - } -} -#endif - -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - LDMIA r0 !, {r1, r2, r3} ORRS r1, r2 ORRS r1, r3 LDMIA r0 !, {r2, r3} ORRS r1, - r2 ORRS r1, r3 LDMIA r0, {r0, r2, r3} ORRS r1, r0 ORRS r1, r2 ORRS r1, - r3 RSBS r1, r1, -# 0 // C set if zero - MOVS r0, -# 0 ADCS r0, r0 BX lr -#else - LDMIA r0 !, {r1, r2, r3, ip} ORRS r1, r2 ORRS r1, r3 ORRS r1, ip LDMIA r0, - {r0, r2, r3, ip} ORRS r1, r0 ORRS r1, r2 ORRS r1, r3 ORRS r1, - ip -#ifdef __ARM_FEATURE_CLZ - CLZ r0, - r1 // 32 if zero - LSRS r0, - r0, -# 5 -#else - RSBS r1, - r1, -# 0 // C set if zero - MOVS r0, -# 0 ADCS r0, - r0 -#endif - BX lr -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { - uECC_word_t ret; -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if defined __thumb__ && !defined __thumb2__ - register uECC_word_t r1 asm("r1"); - register uECC_word_t r2 asm("r2"); - register uECC_word_t r3 asm("r3"); - asm volatile(".syntax unified \n\t" - "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "LDMIA %[vli]!,{%[r2],%[r3]} \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t" - "ORRS %[r1],%[vli] \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "RSBS %[r1],%[r1],#0 \n\t" // C set if zero - "MOVS %[ret],#0 \n\t" - "ADCS %[ret],r0 \n\t" - ".syntax divided \n\t" - : [ ret ] "=r"(ret), [ r1 ] "=r"(r1), [ r2 ] "=r"(r2), - [ r3 ] "=r"(r3) - : [ vli ] "[ret]"(vli) - : "cc", "memory"); -#else - register uECC_word_t r1 asm("r1"); - register uECC_word_t r2 asm("r2"); - register uECC_word_t r3 asm("r3"); - register uECC_word_t ip asm("ip"); - asm volatile( - "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "ORRS %[r1],%[ip] \n\t" - "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t" - "ORRS %[r1],%[vli] \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "ORRS %[r1],%[ip] \n\t" -#if __ARM_ARCH >= 5 - "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero - "LSRS %[ret],%[ret],#5 \n\t" -#else - "RSBS %[r1],%[r1],#0 \n\t" // C set if zero - "MOVS %[ret],#0 \n\t" - "ADCS %[ret],r0 \n\t" -#endif - : [ ret ] "=r"(ret), [ r1 ] "=r"(r1), [ r2 ] "=r"(r2), [ r3 ] "=r"(r3), - [ ip ] "=r"(ip) - : [ vli ] "[ret]"(vli) - : "cc", "memory"); -#endif - return ret; -} -#else -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { - uECC_word_t bits = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - bits |= vli[i]; - } - return (bits == 0); -} -#endif - -uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { - return (vli[bit >> uECC_WORD_BITS_SHIFT] & - ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); -} - -/* Counts the number of words in vli. */ -static wordcount_t vli_numDigits(const uECC_word_t *vli) { - - wordcount_t i; - /* Search from the end until we find a non-zero digit. We do it in reverse - * because we expect that most digits will be nonzero. */ - for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) { - } - - return (i + 1); -} - -bitcount_t uECC_vli_numBits(const uECC_word_t *vli) { - - uECC_word_t i; - uECC_word_t digit; - - wordcount_t num_digits = vli_numDigits(vli); - if (num_digits == 0) { - return 0; - } - - digit = vli[num_digits - 1]; -#if defined __GNUC__ || defined __clang__ || defined __CC_ARM - i = uECC_WORD_BITS - __builtin_clz(digit); -#else - for (i = 0; digit; ++i) { - digit >>= 1; - } -#endif - - return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); -} - -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src) { - wordcount_t i; - - for (i = 0; i < NUM_ECC_WORDS; ++i) { - dest[i] = src[i]; - } -} - -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, - const uECC_word_t *right) { - wordcount_t i; - - for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { - if (left[i] > right[i]) { - return 1; - } else if (left[i] < right[i]) { - return -1; - } - } - return 0; -} - -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right) { - - uECC_word_t diff = 0; - uECC_word_t flow_monitor = 0; - uECC_word_t tmp1, tmp2; - volatile int i; - - /* Start from a random location and check the correct number of iterations */ - int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS); - - for (i = start_offset; i < NUM_ECC_WORDS; ++i) { - tmp1 = left[i]; - tmp2 = right[i]; - flow_monitor++; - diff |= (tmp1 ^ tmp2); - } - - for (i = 0; i < start_offset; ++i) { - tmp1 = left[i]; - tmp2 = right[i]; - flow_monitor++; - diff |= (tmp1 ^ tmp2); - } - - /* Random delay to increase security */ - mbedtls_platform_random_delay(); - - /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */ - return (diff | (flow_monitor ^ NUM_ECC_WORDS)); -} - -uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, - unsigned int cond) { - return (p_true * (cond)) | (p_false * (cond ^ 1)); -} - -/* Computes result = left - right, returning borrow, in constant time. - * Can modify in place. */ -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{r4 - r6, lr} FRAME PUSH{r4 - r6, lr} LDMIA r1 !, {r3, r4} LDMIA r2 !, - {r5, r6} SUBS r3, r5 SBCS r4, r6 STMIA r0 !, {r3, r4} LDMIA r1 !, - {r3, r4} LDMIA r2 !, {r5, r6} SBCS r3, r5 SBCS r4, r6 STMIA r0 !, - {r3, r4} LDMIA r1 !, {r3, r4} LDMIA r2 !, {r5, r6} SBCS r3, r5 SBCS r4, - r6 STMIA r0 !, {r3, r4} LDMIA r1 !, {r3, r4} LDMIA r2 !, {r5, r6} SBCS r3, - r5 SBCS r4, r6 STMIA r0 !, {r3, r4} SBCS r0, - r0 // r0 := r0 - r0 - borrow = -borrow - RSBS r0, - r0, -# 0 // r0 := borrow - POP { - r4 - r6, pc - } -#else - PUSH{r4 - r8, lr} FRAME PUSH{r4 - r8, lr} LDMIA r1 !, {r3 - r6} LDMIA r2 !, - {r7, r8, r12, lr} SUBS r3, r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, - lr STMIA r0 !, {r3 - r6} LDMIA r1 !, {r3 - r6} LDMIA r2 !, - {r7, r8, r12, lr} SBCS r3, r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, - lr STMIA r0 !, {r3 - r6} SBCS r0, - r0 // r0 := r0 - r0 - borrow = -borrow - RSBS r0, - r0, -# 0 // r0 := borrow - POP { - r4 - r8, pc - } -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif - register uECC_word_t *r0 asm("r0") = result; - register const uECC_word_t *r1 asm("r1") = left; - register const uECC_word_t *r2 asm("r2") = right; - asm volatile( -#if defined __thumb__ && !defined __thumb2__ - ".syntax unified \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "SUBS r3,r5 \n\t" - "SBCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "SBCS r3,r5 \n\t" - "SBCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "SBCS r3,r5 \n\t" - "SBCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "SBCS r3,r5 \n\t" - "SBCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow - "RSBS r0,r0,#0 \n\t" // r0 := borrow - ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "r4", "r5", "r6", "cc", "memory" -#else - "LDMIA r1!,{r3-r6} \n\t" - "LDMIA r2!,{r7,r8,r12,lr} \n\t" - "SUBS r3,r7 \n\t" - "SBCS r4,r8 \n\t" - "SBCS r5,r12 \n\t" - "SBCS r6,lr \n\t" - "STMIA r0!,{r3-r6} \n\t" - "LDMIA r1!,{r3-r6} \n\t" - "LDMIA r2!,{r7,r8,r12,lr} \n\t" - "SBCS r3,r7 \n\t" - "SBCS r4,r8 \n\t" - "SBCS r5,r12 \n\t" - "SBCS r6,lr \n\t" - "STMIA r0!,{r3-r6} \n\t" - "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow - "RSBS r0,r0,#0 \n\t" // r0 := borrow - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" -#endif - ); - return (uECC_word_t)r0; -} -#else -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - uECC_word_t diff = left[i] - right[i] - borrow; - uECC_word_t val = (diff > left[i]); - borrow = cond_set(val, borrow, (diff != left[i])); - - result[i] = diff; - } - return borrow; -} -#endif - -/* Computes result = left + right, returning carry, in constant time. - * Can modify in place. */ -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, - const uECC_word_t *left, - const uECC_word_t *right) { -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{r4 - r6, lr} FRAME PUSH{r4 - r6, lr} LDMIA r1 !, {r3, r4} LDMIA r2 !, - {r5, r6} ADDS r3, r5 ADCS r4, r6 STMIA r0 !, {r3, r4} LDMIA r1 !, - {r3, r4} LDMIA r2 !, {r5, r6} ADCS r3, r5 ADCS r4, r6 STMIA r0 !, - {r3, r4} LDMIA r1 !, {r3, r4} LDMIA r2 !, {r5, r6} ADCS r3, r5 ADCS r4, - r6 STMIA r0 !, {r3, r4} LDMIA r1 !, {r3, r4} LDMIA r2 !, {r5, r6} ADCS r3, - r5 ADCS r4, r6 STMIA r0 !, {r3, r4} MOVS r0, -# 0 // does not affect C flag - ADCS r0, - r0 // r0 := 0 + 0 + C = carry - POP { - r4 - r6, pc - } -#else - PUSH{r4 - r8, lr} FRAME PUSH{r4 - r8, lr} LDMIA r1 !, {r3 - r6} LDMIA r2 !, - {r7, r8, r12, lr} ADDS r3, r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, - lr STMIA r0 !, {r3 - r6} LDMIA r1 !, {r3 - r6} LDMIA r2 !, - {r7, r8, r12, lr} ADCS r3, r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, - lr STMIA r0 !, {r3 - r6} MOVS r0, -# 0 // does not affect C flag - ADCS r0, - r0 // r0 := 0 + 0 + C = carry - POP { - r4 - r8, pc - } -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { - register uECC_word_t *r0 asm("r0") = result; - register const uECC_word_t *r1 asm("r1") = left; - register const uECC_word_t *r2 asm("r2") = right; - - asm volatile( -#if defined __thumb__ && !defined __thumb2__ - ".syntax unified \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "ADDS r3,r5 \n\t" - "ADCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "ADCS r3,r5 \n\t" - "ADCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "ADCS r3,r5 \n\t" - "ADCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "LDMIA r1!,{r3,r4} \n\t" - "LDMIA r2!,{r5,r6} \n\t" - "ADCS r3,r5 \n\t" - "ADCS r4,r6 \n\t" - "STMIA r0!,{r3,r4} \n\t" - "MOVS r0,#0 \n\t" // does not affect C flag - "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry - ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "r4", "r5", "r6", "cc", "memory" -#else - "LDMIA r1!,{r3-r6} \n\t" - "LDMIA r2!,{r7,r8,r12,lr} \n\t" - "ADDS r3,r7 \n\t" - "ADCS r4,r8 \n\t" - "ADCS r5,r12 \n\t" - "ADCS r6,lr \n\t" - "STMIA r0!,{r3-r6} \n\t" - "LDMIA r1!,{r3-r6} \n\t" - "LDMIA r2!,{r7,r8,r12,lr} \n\t" - "ADCS r3,r7 \n\t" - "ADCS r4,r8 \n\t" - "ADCS r5,r12 \n\t" - "ADCS r6,lr \n\t" - "STMIA r0!,{r3-r6} \n\t" - "MOVS r0,#0 \n\t" // does not affect C flag - "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" -#endif - ); - return (uECC_word_t)r0; -} -#else -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { - uECC_word_t carry = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - uECC_word_t sum = left[i] + right[i] + carry; - uECC_word_t val = (sum < left[i]); - carry = cond_set(val, carry, (sum != left[i])); - result[i] = sum; - } - return carry; -} -#endif - -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t neg = uECC_vli_sub(tmp, left, right); - uECC_word_t equal = uECC_vli_isZero(tmp); - return ((equal ^ 1) - 2 * neg); -} - -/* Computes vli = vli >> 1. */ -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -static __asm void uECC_vli_rshift1(uECC_word_t *vli) { -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - // RRX instruction is not available, so although we - // can use C flag, it's not that effective. Does at - // least save one working register, meaning we don't need stack - MOVS r3, -# 0 // initial carry = 0 - MOVS r2, -#__cpp(4 * (NUM_ECC_WORDS - 1)) 01 LDR r1, [r0, r2] LSRS r1, r1, -# 1 // r2 = word >> 1 - ORRS r1, - r3 // merge in the previous carry - STR r1, - [ r0, r2 ] ADCS r3, - r3 // put C into bottom bit of r3 - LSLS r3, - r3, -# 31 // shift it up to the top ready for next word - SUBS r2, r2, #4 BPL % B01 BX lr -#else -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif - // Smooth multiword operation, lots of 32-bit instructions - ADDS r0, #32 LDMDB r0, {r1 - r3, ip} LSRS ip, ip, #1 RRXS r3, r3 RRXS r2, - r2 RRXS r1, r1 STMDB r0 !, {r1 - r3, ip} LDMDB r0, {r1 - r3, ip} RRXS ip, - ip RRXS r3, r3 RRXS r2, r2 RRX r1, r1 STMDB r0 !, {r1 - r3, ip} BX lr -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ && \ - defined __thumb2__ -static void uECC_vli_rshift1(uECC_word_t *vli) { - register uECC_word_t *r0 asm("r0") = vli; -#if NUM_ECC_WORDS != 8 -#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 -#endif - asm volatile("ADDS r0,#32 \n\t" - "LDMDB r0,{r1-r3,ip} \n\t" - "LSRS ip,ip,#1 \n\t" - "RRXS r3,r3 \n\t" - "RRXS r2,r2 \n\t" - "RRXS r1,r1 \n\t" - "STMDB r0!,{r1-r3,ip} \n\t" - "LDMDB r0,{r1-r3,ip} \n\t" - "RRXS ip,ip \n\t" - "RRXS r3,r3 \n\t" - "RRXS r2,r2 \n\t" - "RRX r1,r1 \n\t" - "STMDB r0!,{r1-r3,ip} \n\t" - : "+r"(r0) - : - : "r1", "r2", "r3", "ip", "cc", "memory"); -} -#else -static void uECC_vli_rshift1(uECC_word_t *vli) { - uECC_word_t *end = vli; - uECC_word_t carry = 0; - - vli += NUM_ECC_WORDS; - while (vli-- > end) { - uECC_word_t temp = *vli; - *vli = (temp >> 1) | carry; - carry = temp << (uECC_WORD_BITS - 1); - } -} -#endif - -/* Compute a * b + r, where r is a triple-word with high-order word r[2] and - * low-order word r[0], and store the result in the same triple-word. - * - * r[2..0] = a * b + r[2..0]: - * [in] a, b: operands to be multiplied - * [in] r: 3 words of operand to add - * [out] r: 3 words of result - */ -#if defined OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{r4 - r5} FRAME PUSH{r4 - r5} - // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 - // Separate operands into halfwords - UXTH r3, - r0 // r3 := a.lo - LSRS r4, - r0, -# 16 // r4 := a.hi - UXTH r5, - r1 // r5 := b.lo - LSRS r1, - r1, -# 16 // r1 := b.hi - MOVS r0, r3 MULS r0, r5, // Multiply halfword pairs - r0 // r0 := a.lo * b.lo - MULS r3, - r1, - r3 // r3 := a.lo * b.hi - MULS r5, - r4, - r5 // r5 := a.hi * b.lo - MULS r1, - r4, - r1 // r1 := a.hi * b.hi - // Split, shift and add a.lo * b.hi - LSRS r4, - r3, -# 16 // r4 := (a.lo * b.hi).hi - LSLS r3, r3, -# 16 // r3 := (a.lo * b.hi).lo - ADDS r0, r0, - r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo - ADCS r1, - r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry - // Split, shift and add a.hi * b.lo - LSRS r4, - r5, -# 16 // r4 := (a.hi * b.lo).hi - LSLS r5, r5, -# 16 // r5 := (a.hi * b.lo).lo - ADDS r0, r0, - r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo - ADCS r1, - r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries - // Finally add r[] - LDMIA r2 !, - {r3, r4, r5} ADDS r3, r3, r0 ADCS r4, r1 MOVS r0, #0 ADCS r5, r0 SUBS r2, -# 12 STMIA r2 !, {r3, r4, r5 } POP{r4 - r5 } FRAME POP{r4 - r5 } BX lr -#else - UMULL r3, ip, r0, - r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn - LDMIA r2, - {r0, r1} ADDS r0, r0, r3 LDR r3, [ r2, #8 ] ADCS r1, r1, ip ADC r3, r3, -# 0 STMIA r2 !, {r0, r1, r3 } BX lr -#endif -} -#elif defined OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { - register uECC_word_t r0 asm("r0") = a; - register uECC_word_t r1 asm("r1") = b; - register uECC_word_t *r2 asm("r2") = r; - asm volatile( -#if defined __thumb__ && !defined(__thumb2__) - ".syntax unified \n\t" - // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 - // Separate operands into halfwords - "UXTH r3,r0 \n\t" // r3 := a.lo - "LSRS r4,r0,#16 \n\t" // r4 := a.hi - "UXTH r5,r1 \n\t" // r5 := b.lo - "LSRS r1,r1,#16 \n\t" // r1 := b.hi - // Multiply halfword pairs - "MOVS r0,r3 \n\t" - "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo - "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi - "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo - "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi - // Split, shift and add a.lo * b.hi - "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi - "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo - "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo - "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi - // + carry - // Split, shift and add a.hi * b.lo - "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi - "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo - "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo - // + (a.hi * b.lo).lo - "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi - // + (a.hi * b.lo).hi + carries - // Finally add r[] - "LDMIA r2!,{r3,r4,r5} \n\t" - "ADDS r3,r3,r0 \n\t" - "ADCS r4,r1 \n\t" - "MOVS r0,#0 \n\t" - "ADCS r5,r0 \n\t" - "SUBS r2,#12 \n\t" - "STMIA r2!,{r3,r4,r5} \n\t" - ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "r4", "r5", "ip", "cc", "memory" -#else - "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn - "LDMIA r2,{r0,r1} \n\t" - "ADDS r0,r0,r3 \n\t" - "LDR r3,[r2,#8] \n\t" - "ADCS r1,r1,ip \n\t" - "ADC r3,r3,#0 \n\t" - "STMIA r2!,{r0,r1,r3} \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) - : - : "r3", "ip", "cc", "memory" -#endif - ); -} -#else -static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { - - uECC_dword_t p = (uECC_dword_t)a * b; - uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0]; - r01 += p; - r[2] += (r01 < p); - r[1] = r01 >> uECC_WORD_BITS; - r[0] = (uECC_word_t)r01; -} -#endif - -/* State for implementing random delays in uECC_vli_mult_rnd(). - * - * The state is initialized by randomizing delays and setting i = 0. - * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i. - * - * Randomized vli multiplication is used only for point operations - * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication - * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to - * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(), - * indirectly through uECC_vli_modMult_rnd(). - * - * Considering this, in order to minimize the number of calls to the RNG - * (which impact performance) while keeping the size of the structure low, - * make room for 14 randomized vli mults, which corresponds to one step in the - * scalar multiplication routine. - */ -typedef struct { - uint8_t i; - uint8_t delays[14]; -} ecc_wait_state_t; - -/* - * Reset wait_state so that it's ready to be used. - */ -void ecc_wait_state_reset(ecc_wait_state_t *ws) { - if (ws == NULL) - return; - - ws->i = 0; - mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays)); -} - -/* Computes result = left * right. Result must be 2 * num_words long. - * - * As a counter-measure against horizontal attacks, add noise by performing - * a random number of extra computations performing random additional accesses - * to limbs of the input. - * - * Each of the two actual computation loops is surrounded by two - * similar-looking waiting loops, to make the beginning and end of the actual - * computation harder to spot. - * - * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That - * makes an average of 6 extra calls. Compared to the main computation which - * makes 64 such calls, this represents an average performance degradation of - * less than 10%. - * - * Compared to the original uECC_vli_mult(), loose the num_words argument as we - * know it's always 8. This saves a bit of code size and execution speed. - */ -static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, ecc_wait_state_t *s) { - - uECC_word_t r[3] = {0, 0, 0}; - wordcount_t i, k; - const uint8_t num_words = NUM_ECC_WORDS; - - /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ - uint8_t delays = s ? s->delays[s->i++] : 0; - uECC_word_t rr[3] = {0, 0, 0}; - volatile uECC_word_t rdummy; - - /* Mimic start of next loop: k in [0, 3] */ - k = 0 + (delays & 0x03); - delays >>= 2; - /* k = 0 -> i in [1, 0] -> 0 extra muladd; - * k = 3 -> i in [1, 3] -> 3 extra muladd */ - for (i = 1; i <= k; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - - /* Compute each digit of result in sequence, maintaining the carries. */ - for (k = 0; k < num_words; ++k) { - for (i = 0; i <= k; ++i) { - muladd(left[i], right[k - i], r); - } - - result[k] = r[0]; - r[0] = r[1]; - r[1] = r[2]; - r[2] = 0; - } - - /* Mimic end of previous loop: k in [4, 7] */ - k = 4 + (delays & 0x03); - delays >>= 2; - /* k = 4 -> i in [5, 4] -> 0 extra muladd; - * k = 7 -> i in [5, 7] -> 3 extra muladd */ - for (i = 5; i <= k; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - - /* Mimic start of next loop: k in [8, 11] */ - k = 11 - (delays & 0x03); - delays >>= 2; - /* k = 8 -> i in [5, 7] -> 3 extra muladd; - * k = 11 -> i in [8, 7] -> 0 extra muladd */ - for (i = (k + 5) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - - for (k = num_words; k < num_words * 2 - 1; ++k) { - - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], r); - } - result[k] = r[0]; - r[0] = r[1]; - r[1] = r[2]; - r[2] = 0; - } - - result[num_words * 2 - 1] = r[0]; - - /* Mimic end of previous loop: k in [12, 15] */ - k = 15 - (delays & 0x03); - delays >>= 2; - /* k = 12 -> i in [5, 7] -> 3 extra muladd; - * k = 15 -> i in [8, 7] -> 0 extra muladd */ - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - - /* avoid warning that rdummy is set but not used */ - (void)rdummy; -} - -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t carry = uECC_vli_add(result, left, right); - if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { - /* result > mod (result = mod + remainder), so subtract mod to get - * remainder. */ - uECC_vli_sub(result, result, mod); - } -} - -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t l_borrow = uECC_vli_sub(result, left, right); - if (l_borrow) { - /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, - * we can get the correct result from result + mod (with overflow). */ - uECC_vli_add(result, result, mod); - } -} - -/* Computes result = product % mod, where product is 2N words long. */ -/* Currently only designed to work for curve_p or curve_n. */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod) { - uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; - uECC_word_t tmp[2 * NUM_ECC_WORDS]; - uECC_word_t *v[2] = {tmp, product}; - uECC_word_t index; - const wordcount_t num_words = NUM_ECC_WORDS; - - /* Shift mod so its highest set bit is at the maximum position. */ - bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod); - wordcount_t word_shift = shift / uECC_WORD_BITS; - wordcount_t bit_shift = shift % uECC_WORD_BITS; - uECC_word_t carry = 0; - - if (word_shift > NUM_ECC_WORDS) { - mbedtls_platform_fault(); - } - - uECC_vli_clear(mod_multiple); - if (bit_shift > 0) { - for (index = 0; index < (uECC_word_t)num_words; ++index) { - mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; - carry = mod[index] >> (uECC_WORD_BITS - bit_shift); - } - } else { - uECC_vli_set(mod_multiple + word_shift, mod); - } - - for (index = 1; shift >= 0; --shift) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words * 2; ++i) { - uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; - if (diff != v[index][i]) { - borrow = (diff > v[index][i]); - } - v[1 - index][i] = diff; - } - /* Swap the index if there was no borrow */ - index = !(index ^ borrow); - uECC_vli_rshift1(mod_multiple); - mod_multiple[num_words - 1] |= mod_multiple[num_words] - << (uECC_WORD_BITS - 1); - uECC_vli_rshift1(mod_multiple + num_words); - } - uECC_vli_set(result, v[index]); -} - -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult_rnd(product, left, right, NULL); - uECC_vli_mmod(result, product, mod); -} - -static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, - ecc_wait_state_t *s) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult_rnd(product, left, right, s); - - vli_mmod_fast_secp256r1(result, product); -} - -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right) { - uECC_vli_modMult_rnd(result, left, right, NULL); -} - -#define EVEN(vli) (!(vli[0] & 1)) - -static void vli_modInv_update(uECC_word_t *uv, const uECC_word_t *mod) { - - uECC_word_t carry = 0; - - if (!EVEN(uv)) { - carry = uECC_vli_add(uv, uv, mod); - } - uECC_vli_rshift1(uv); - if (carry) { - uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET; - } -} - -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod) { - uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; - uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; - cmpresult_t cmpResult; - - if (uECC_vli_isZero(input)) { - uECC_vli_clear(result); - return; - } - - uECC_vli_set(a, input); - uECC_vli_set(b, mod); - uECC_vli_clear(u); - u[0] = 1; - uECC_vli_clear(v); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { - if (EVEN(a)) { - uECC_vli_rshift1(a); - vli_modInv_update(u, mod); - } else if (EVEN(b)) { - uECC_vli_rshift1(b); - vli_modInv_update(v, mod); - } else if (cmpResult > 0) { - uECC_vli_sub(a, a, b); - uECC_vli_rshift1(a); - if (uECC_vli_cmp_unsafe(u, v) < 0) { - uECC_vli_add(u, u, mod); - } - uECC_vli_sub(u, u, v); - vli_modInv_update(u, mod); - } else { - uECC_vli_sub(b, b, a); - uECC_vli_rshift1(b); - if (uECC_vli_cmp_unsafe(v, u) < 0) { - uECC_vli_add(v, v, mod); - } - uECC_vli_sub(v, v, u); - vli_modInv_update(v, mod); - } - } - uECC_vli_set(result, u); -} - -/* ------ Point operations ------ */ - -void double_jacobian_default(uECC_word_t *X1, uECC_word_t *Y1, - uECC_word_t *Z1) { - /* t1 = X, t2 = Y, t3 = Z */ - uECC_word_t t4[NUM_ECC_WORDS]; - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - - if (uECC_vli_isZero(Z1)) { - return; - } - - uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */ - uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */ - uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */ - uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ - uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ - - uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */ - uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */ - uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */ - uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ - - uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */ - uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */ - if (uECC_vli_testBit(X1, 0)) { - uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p); - uECC_vli_rshift1(X1); - X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); - } else { - uECC_vli_rshift1(X1); - } - - /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ - uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */ - uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */ - uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */ - uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ - /* t4 = B * (A - x3) - y1^4 = y3: */ - uECC_vli_modSub(t4, X1, t4, curve_p); - - uECC_vli_set(X1, Z1); - uECC_vli_set(Z1, Y1); - uECC_vli_set(Y1, t4); -} - -/* - * @brief Computes x^3 + ax + b. result must not overlap x. - * @param result OUT -- x^3 + ax + b - * @param x IN -- value of x - * @param curve IN -- elliptic curve - */ -static void x_side_default(uECC_word_t *result, const uECC_word_t *x) { - uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ - - uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ - uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */ - uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ - /* r = x^3 - 3x + b: */ - uECC_vli_modAdd(result, result, curve_b, curve_p); -} - -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product) { - unsigned int tmp[NUM_ECC_WORDS]; - int carry; - - /* t */ - uECC_vli_set(result, product); - - /* s1 */ - tmp[0] = tmp[1] = tmp[2] = 0; - tmp[3] = product[11]; - tmp[4] = product[12]; - tmp[5] = product[13]; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry = uECC_vli_add(tmp, tmp, tmp); - carry += uECC_vli_add(result, result, tmp); - - /* s2 */ - tmp[3] = product[12]; - tmp[4] = product[13]; - tmp[5] = product[14]; - tmp[6] = product[15]; - tmp[7] = 0; - carry += uECC_vli_add(tmp, tmp, tmp); - carry += uECC_vli_add(result, result, tmp); - - /* s3 */ - tmp[0] = product[8]; - tmp[1] = product[9]; - tmp[2] = product[10]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry += uECC_vli_add(result, result, tmp); - - /* s4 */ - tmp[0] = product[9]; - tmp[1] = product[10]; - tmp[2] = product[11]; - tmp[3] = product[13]; - tmp[4] = product[14]; - tmp[5] = product[15]; - tmp[6] = product[13]; - tmp[7] = product[8]; - carry += uECC_vli_add(result, result, tmp); - - /* d1 */ - tmp[0] = product[11]; - tmp[1] = product[12]; - tmp[2] = product[13]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[8]; - tmp[7] = product[10]; - carry -= uECC_vli_sub(result, result, tmp); - - /* d2 */ - tmp[0] = product[12]; - tmp[1] = product[13]; - tmp[2] = product[14]; - tmp[3] = product[15]; - tmp[4] = tmp[5] = 0; - tmp[6] = product[9]; - tmp[7] = product[11]; - carry -= uECC_vli_sub(result, result, tmp); - - /* d3 */ - tmp[0] = product[13]; - tmp[1] = product[14]; - tmp[2] = product[15]; - tmp[3] = product[8]; - tmp[4] = product[9]; - tmp[5] = product[10]; - tmp[6] = 0; - tmp[7] = product[12]; - carry -= uECC_vli_sub(result, result, tmp); - - /* d4 */ - tmp[0] = product[14]; - tmp[1] = product[15]; - tmp[2] = 0; - tmp[3] = product[9]; - tmp[4] = product[10]; - tmp[5] = product[11]; - tmp[6] = 0; - tmp[7] = product[13]; - carry -= uECC_vli_sub(result, result, tmp); - - if (carry < 0) { - do { - carry += uECC_vli_add(result, result, curve_p); - } while (carry < 0); - } else { - while (carry || uECC_vli_cmp_unsafe(curve_p, result) != 1) { - carry -= uECC_vli_sub(result, result, curve_p); - } - } -} - -uECC_word_t EccPoint_isZero(const uECC_word_t *point) { - return uECC_vli_isZero(point); -} - -void apply_z(uECC_word_t *X1, uECC_word_t *Y1, const uECC_word_t *const Z) { - uECC_word_t t1[NUM_ECC_WORDS]; - - uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */ - uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */ - uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */ - uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */ -} - -/* P = (x1, y1) => 2P, (x2, y2) => P' */ -static void XYcZ_initial_double(uECC_word_t *X1, uECC_word_t *Y1, - uECC_word_t *X2, uECC_word_t *Y2, - const uECC_word_t *const initial_Z) { - uECC_word_t z[NUM_ECC_WORDS]; - if (initial_Z) { - uECC_vli_set(z, initial_Z); - } else { - uECC_vli_clear(z); - z[0] = 1; - } - - uECC_vli_set(X2, X1); - uECC_vli_set(Y2, Y1); - - apply_z(X1, Y1, z); - double_jacobian_default(X1, Y1, z); - apply_z(X2, Y2, z); -} - -static void XYcZ_add_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, - uECC_word_t *Y2, ecc_wait_state_t *s) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - - uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ - uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ - uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ - uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ - - uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */ - uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */ - uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */ - - uECC_vli_set(X2, t5); -} - -void XYcZ_add(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, - uECC_word_t *Y2) { - XYcZ_add_rnd(X1, Y1, X2, Y2, NULL); -} - -/* Input P = (x1, y1, Z), Q = (x2, y2, Z) - Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) - or P => P - Q, Q => P + Q - */ -static void XYcZ_addC_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, - uECC_word_t *Y2, ecc_wait_state_t *s) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - uECC_word_t t6[NUM_ECC_WORDS]; - uECC_word_t t7[NUM_ECC_WORDS]; - - uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ - uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ - uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ - - uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */ - uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ - uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */ - uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ - uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */ - - uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */ - uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ - /* t4 = (y2 - y1)*(B - x3) - E = y3: */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); - - uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ - uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */ - uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */ - uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ - /* t2 = (y2+y1)*(x3' - B) - E = y3': */ - uECC_vli_modSub(Y1, t6, Y1, curve_p); - - uECC_vli_set(X1, t7); -} - -static void EccPoint_mult(uECC_word_t *result, const uECC_word_t *point, - const uECC_word_t *scalar, - const uECC_word_t *initial_Z) { - /* R0 and R1 */ - uECC_word_t Rx[2][NUM_ECC_WORDS]; - uECC_word_t Ry[2][NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - bitcount_t i; - uECC_word_t nb; - const wordcount_t num_words = NUM_ECC_WORDS; - const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */ - ecc_wait_state_t wait_state; - ecc_wait_state_t *const ws = g_rng_function ? &wait_state : NULL; - - uECC_vli_set(Rx[1], point); - uECC_vli_set(Ry[1], point + num_words); - - XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z); - - for (i = num_bits - 2; i > 0; --i) { - ecc_wait_state_reset(ws); - nb = !uECC_vli_testBit(scalar, i); - XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); - XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); - } - - ecc_wait_state_reset(ws); - nb = !uECC_vli_testBit(scalar, 0); - XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); - - /* Find final 1/Z value. */ - uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */ - uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ - uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ - uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/ - /* yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, point + num_words); - /* Xb * yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, Rx[1 - nb]); - /* End 1/Z calculation */ - - XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); - apply_z(Rx[0], Ry[0], z); - - uECC_vli_set(result, Rx[0]); - uECC_vli_set(result + num_words, Ry[0]); -} - -static uECC_word_t regularize_k(const uECC_word_t *const k, uECC_word_t *k0, - uECC_word_t *k1) { - wordcount_t num_n_words = NUM_ECC_WORDS; - bitcount_t num_n_bits = NUM_ECC_BITS; - - /* With our constant NUM_ECC_BITS and NUM_ECC_WORDS the - * check (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) always - * would have "false" result (256 < 256), therefore Coverity warning may be - * detected. Removing of this line without changing the entire check will - * cause to array overrun. The entire check is not changed on purpose to be - * aligned with original tinycrypt implementation and to allow upstreaming to - * other curves if required. Coverity specific annotation may be added to - * silence warning if exists. - */ - uECC_word_t carry = - uECC_vli_add(k0, k, curve_n) || - (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && - uECC_vli_testBit(k0, num_n_bits)); - - uECC_vli_add(k1, k0, curve_n); - - return carry; -} - -int EccPoint_mult_safer(uECC_word_t *result, const uECC_word_t *point, - const uECC_word_t *scalar) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t *k2[2] = {tmp, s}; - wordcount_t num_words = NUM_ECC_WORDS; - uECC_word_t carry; - uECC_word_t *initial_Z = 0; - int r = UECC_FAULT_DETECTED; - volatile int problem; - - /* Protect against faults modifying curve paremeters in flash */ - problem = -1; - problem = uECC_check_curve_integrity(); - if (problem != 0) { - return UECC_FAULT_DETECTED; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - return UECC_FAULT_DETECTED; - } - - /* Protects against invalid curve attacks */ - problem = -1; - problem = uECC_valid_point(point); - if (problem != 0) { - /* invalid input, can happen without fault */ - return UECC_FAILURE; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - /* failure on second check means fault, though */ - return UECC_FAULT_DETECTED; - } - - /* Regularize the bitcount for the private key so that attackers cannot use a - * side channel attack to learn the number of leading zeros. */ - carry = regularize_k(scalar, tmp, s); - - /* If an RNG function was specified, get a random initial Z value to - * protect against side-channel attacks such as Template SPA */ - if (g_rng_function) { - if (uECC_generate_random_int(k2[carry], curve_p, num_words) != - UECC_SUCCESS) { - r = UECC_FAILURE; - goto clear_and_out; - } - initial_Z = k2[carry]; - } - - EccPoint_mult(result, point, k2[!carry], initial_Z); - - /* Protect against fault injections that would make the resulting - * point not lie on the intended curve */ - problem = -1; - problem = uECC_valid_point(result); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - - /* Protect against faults modifying curve paremeters in flash */ - problem = -1; - problem = uECC_check_curve_integrity(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - - r = UECC_SUCCESS; - -clear_and_out: - /* erasing temporary buffer used to store secret: */ - mbedtls_platform_zeroize(k2, sizeof(k2)); - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - mbedtls_platform_zeroize(s, sizeof(s)); - - return r; -} - -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key) { - return EccPoint_mult_safer(result, curve_G, private_key); -} - -/* Converts an integer in uECC native format to big-endian bytes. */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native) { - wordcount_t i; - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); - } -} - -/* Converts big-endian bytes to an integer in uECC native format. */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes) { - wordcount_t i; - uECC_vli_clear(native); - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - native[b / uECC_WORD_SIZE] |= (uECC_word_t)bytes[i] - << (8 * (b % uECC_WORD_SIZE)); - } -} - -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words) { - uECC_word_t mask = (uECC_word_t)-1; - uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top); - - if (!g_rng_function) { - return UECC_FAILURE; - } - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != - num_words * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - random[num_words - 1] &= - mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random) && uECC_vli_cmp(top, random) == 1) { - return UECC_SUCCESS; - } - } - return UECC_FAILURE; -} - -int uECC_valid_point(const uECC_word_t *point) { - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - volatile uECC_word_t diff = 0xffffffff; - - /* The point at infinity is invalid. */ - if (EccPoint_isZero(point)) { - return -1; - } - - /* x and y must be smaller than p. */ - if (uECC_vli_cmp_unsafe(curve_p, point) != 1 || - uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) { - return -2; - } - - uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words); - x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */ - - /* Make sure that y^2 == x^3 + ax + b */ - diff = uECC_vli_equal(tmp1, tmp2); - if (diff == 0) { - mbedtls_platform_random_delay(); - if (diff == 0) { - return 0; - } - } - - return -3; -} - -int uECC_valid_public_key(const uint8_t *public_key) { - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); - uECC_vli_bytesToNative(_public + NUM_ECC_WORDS, public_key + NUM_ECC_BYTES, - NUM_ECC_BYTES); - - if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) { - return -4; - } - - return uECC_valid_point(_public); -} - -int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative(_private, private_key, TC_BITS_TO_BYTES(NUM_ECC_BITS)); - - /* Make sure the private key is in the range [1, n-1]. */ - if (uECC_vli_isZero(_private)) { - return UECC_FAILURE; - } - - if (uECC_vli_cmp(curve_n, _private) != 1) { - return UECC_FAILURE; - } - - /* Compute public key. */ - ret = EccPoint_compute_public_key(_public, _private); - if (ret != UECC_SUCCESS) { - return ret; - } - - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, - _public + NUM_ECC_WORDS); - - return ret; -} -#endif /* TINYCRYPT_PRIMITIVES */ +/* ecc.c - TinyCrypt implementation of common ECC functions */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform + * has access to enough entropy in order to feed the PRNG regularly. */ +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_CSPRNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +void uECC_set_rng(uECC_RNG_Function rng_function) +{ + g_rng_function = rng_function; +} + +uECC_RNG_Function uECC_get_rng(void) +{ + return g_rng_function; +} + +int uECC_curve_private_key_size(uECC_Curve curve) +{ + return BITS_TO_BYTES(curve->num_n_bits); +} + +int uECC_curve_public_key_size(uECC_Curve curve) +{ + return 2 * curve->num_bytes; +} + +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) +{ + wordcount_t i; + for (i = 0; i < num_words; ++i) { + vli[i] = 0; + } +} + +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) +{ + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + bits |= vli[i]; + } + return (bits == 0); +} + +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) +{ + return (vli[bit >> uECC_WORD_BITS_SHIFT] & + ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); +} + +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, + const wordcount_t max_words) +{ + + wordcount_t i; + /* Search from the end until we find a non-zero digit. We do it in reverse + * because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + } + + return (i + 1); +} + +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, + const wordcount_t max_words) +{ + + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); +} + +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, + wordcount_t num_words) +{ + wordcount_t i; + + for (i = 0; i < num_words; ++i) { + dest[i] = src[i]; + } +} + +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) +{ + wordcount_t i; + + for (i = num_words - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; +} + +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words) +{ + + uECC_word_t diff = 0; + wordcount_t i; + + for (i = num_words - 1; i >= 0; --i) { + diff |= (left[i] ^ right[i]); + } + return !(diff == 0); +} + +uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) +{ + return (p_true*(cond)) | (p_false*(!cond)); +} + +/* Computes result = left - right, returning borrow, in constant time. + * Can modify in place. */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + uECC_word_t val = (diff > left[i]); + borrow = cond_set(val, borrow, (diff != left[i])); + + result[i] = diff; + } + return borrow; +} + +/* Computes result = left + right, returning carry, in constant time. + * Can modify in place. */ +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + uECC_word_t val = (sum < left[i]); + carry = cond_set(val, carry, (sum != left[i])); + result[i] = sum; + } + return carry; +} + +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, + wordcount_t num_words) +{ + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + return (!equal - 2 * neg); +} + +/* Computes vli = vli >> 1. */ +static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) +{ + uECC_word_t *end = vli; + uECC_word_t carry = 0; + + vli += num_words; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } +} + +static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, + uECC_word_t *r1, uECC_word_t *r2) +{ + + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; + +} + +/* Computes result = left * right. Result must be 2 * num_words long. */ +static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t i, k; + + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + + for (k = num_words; k < num_words * 2 - 1; ++k) { + + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words * 2 - 1] = r0; +} + +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get + * remainder. */ + uECC_vli_sub(result, result, mod, num_words); + } +} + +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + * we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + } +} + +/* Computes result = product % mod, where product is 2N words long. */ +/* Currently only designed to work for curve_p or curve_n. */ +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, + const uECC_word_t *mod, wordcount_t num_words) +{ + uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; + uECC_word_t tmp[2 * NUM_ECC_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - + uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + /* Swap the index if there was no borrow */ + index = !(index ^ borrow); + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << + (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words, num_words); + } + uECC_vli_set(result, v[index], num_words); +} + +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod, + wordcount_t num_words) +{ + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult(product, left, right, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} + +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, uECC_Curve curve) +{ + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult(product, left, right, curve->num_words); + + curve->mmod_fast(result, product); +} + +static void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) +{ + uECC_vli_modMult_fast(result, left, left, curve); +} + + +#define EVEN(vli) (!(vli[0] & 1)) + +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) +{ + + uECC_word_t carry = 0; + + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod, num_words); + } + uECC_vli_rshift1(uv, num_words); + if (carry) { + uv[num_words - 1] |= HIGH_BIT_SET; + } +} + +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, + const uECC_word_t *mod, wordcount_t num_words) +{ + uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; + uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + uECC_vli_clear(result, num_words); + return; + } + + uECC_vli_set(a, input, num_words); + uECC_vli_set(b, mod, num_words); + uECC_vli_clear(u, num_words); + u[0] = 1; + uECC_vli_clear(v, num_words); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a, num_words); + vli_modInv_update(u, mod, num_words); + } else if (EVEN(b)) { + uECC_vli_rshift1(b, num_words); + vli_modInv_update(v, mod, num_words); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b, num_words); + uECC_vli_rshift1(a, num_words); + if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + uECC_vli_add(u, u, mod, num_words); + } + uECC_vli_sub(u, u, v, num_words); + vli_modInv_update(u, mod, num_words); + } else { + uECC_vli_sub(b, b, a, num_words); + uECC_vli_rshift1(b, num_words); + if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + uECC_vli_add(v, v, mod, num_words); + } + uECC_vli_sub(v, v, u, num_words); + vli_modInv_update(v, mod, num_words); + } + } + uECC_vli_set(result, u, num_words); +} + +/* ------ Point operations ------ */ + +void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * Z1, uECC_Curve curve) +{ + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[NUM_ECC_WORDS]; + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + if (uECC_vli_isZero(Z1, num_words)) { + return; + } + + uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ + uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ + + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ + + uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); + uECC_vli_rshift1(X1, num_words); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1, num_words); + } + + /* t1 = 3/2*(x1^2 - z1^4) = B */ + uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + /* t4 = B * (A - x3) - y1^4 = y3: */ + uECC_vli_modSub(t4, X1, t4, curve->p, num_words); + + uECC_vli_set(X1, Z1, num_words); + uECC_vli_set(Z1, Y1, num_words); + uECC_vli_set(Y1, t4, num_words); +} + +void x_side_default(uECC_word_t *result, + const uECC_word_t *x, + uECC_Curve curve) +{ + uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ + wordcount_t num_words = curve->num_words; + + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ + /* r = x^3 - 3x + b: */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); +} + +uECC_Curve uECC_secp256r1(void) +{ + return &curve_secp256r1; +} + +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) +{ + unsigned int tmp[NUM_ECC_WORDS]; + int carry; + + /* t */ + uECC_vli_set(result, product, NUM_ECC_WORDS); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + } + while (carry < 0); + } else { + while (carry || + uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + } + } +} + +uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) +{ + return uECC_vli_isZero(point, curve->num_words * 2); +} + +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, + uECC_Curve curve) +{ + uECC_word_t t1[NUM_ECC_WORDS]; + + uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ +} + +/* P = (x1, y1) => 2P, (x2, y2) => P' */ +static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + const uECC_word_t * const initial_Z, + uECC_Curve curve) +{ + uECC_word_t z[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + if (initial_Z) { + uECC_vli_set(z, initial_Z, num_words); + } else { + uECC_vli_clear(z, num_words); + z[0] = 1; + } + + uECC_vli_set(X2, X1, num_words); + uECC_vli_set(Y2, Y1, num_words); + + apply_z(X1, Y1, z, curve); + curve->double_jacobian(X1, Y1, z, curve); + apply_z(X2, Y2, z, curve); +} + +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + + uECC_vli_set(X2, t5, num_words); +} + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) + or P => P - Q, Q => P + Q + */ +static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + uECC_word_t t6[NUM_ECC_WORDS]; + uECC_word_t t7[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + + uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + + uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + /* t4 = (y2 - y1)*(B - x3) - E = y3: */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); + + uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + /* t2 = (y2+y1)*(x3' - B) - E = y3': */ + uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); + + uECC_vli_set(X1, t7, num_words); +} + +void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, uECC_Curve curve) +{ + /* R0 and R1 */ + uECC_word_t Rx[2][NUM_ECC_WORDS]; + uECC_word_t Ry[2][NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words, curve); + /* Xb * yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); + /* End 1/Z calculation */ + + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + apply_z(Rx[0], Ry[0], z, curve); + + uECC_vli_set(result, Rx[0], num_words); + uECC_vli_set(result + num_words, Ry[0], num_words); +} + +uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, + uECC_word_t *k1, uECC_Curve curve) +{ + + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + bitcount_t num_n_bits = curve->num_n_bits; + + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + + uECC_vli_add(k1, k0, curve->n, num_n_words); + + return carry; +} + +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, + uECC_Curve curve) +{ + + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot + * use a side channel attack to learn the number of leading zeros. */ + carry = regularize_k(private_key, tmp1, tmp2, curve); + + EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + + if (EccPoint_isZero(result, curve)) { + return 0; + } + return 1; +} + +/* Converts an integer in uECC native format to big-endian bytes. */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, + const unsigned int *native) +{ + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } +} + +/* Converts big-endian bytes to an integer in uECC native format. */ +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, + int num_bytes) +{ + wordcount_t i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } +} + +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, + wordcount_t num_words) +{ + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= + mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) +{ + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + return -1; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + return -2; + } + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) + return -3; + + return 0; +} + +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) +{ + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + curve->num_words, + public_key + curve->num_bytes, + curve->num_bytes); + + if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { + return -4; + } + + return uECC_valid_point(_public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, + uECC_Curve curve) +{ + + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative( + _private, + private_key, + BITS_TO_BYTES(curve->num_n_bits)); + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + return 0; + } + + /* Compute public key. */ + if (!EccPoint_compute_public_key(_public, _private, curve)) { + return 0; + } + + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + + curve->num_bytes, curve->num_bytes, _public + curve->num_words); + return 1; +} + + + diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index 5d5aaeee91..5624c96446 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -1,182 +1,192 @@ -/* ec_dh.c - TinyCrypt implementation of EC-DH */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the - *documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "mbedtls/platform_util.h" -#include "tinycrypt/ecc.h" -#include "tinycrypt/ecc_dh.h" -#include - -int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, - unsigned int *d) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - /* This function is designed for test purposes-only (such as validating NIST - * test vectors) as it uses a provided value for d instead of generating - * it uniformly at random. */ - if (mbedtls_platform_memcpy(_private, d, NUM_ECC_BYTES) != _private) { - goto exit; - } - - /* Computing public-key from private: */ - ret = EccPoint_compute_public_key(_public, _private); - if (ret != UECC_SUCCESS) { - goto exit; - } - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, TC_BITS_TO_BYTES(NUM_ECC_BITS), _private); - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, - _public + NUM_ECC_WORDS); - -exit: - /* erasing temporary buffer used to store secret: */ - mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); - - return ret; -} - -int uECC_make_key(uint8_t *public_key, uint8_t *private_key) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _random[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t tries; - volatile uint8_t *public_key_dup = public_key; - volatile uint8_t *private_key_dup = private_key; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _private uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != - 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - - /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ - uECC_vli_mmod(_private, _random, curve_n); - - /* Computing public-key from private: */ - ret = EccPoint_compute_public_key(_public, _private); - /* don't try again if a fault was detected */ - if (ret == UECC_FAULT_DETECTED) { - return ret; - } - if (ret == UECC_SUCCESS) { - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, TC_BITS_TO_BYTES(NUM_ECC_BITS), - _private); - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, - _public + NUM_ECC_WORDS); - - /* erasing temporary buffer that stored secret: */ - mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); - - if (private_key == private_key_dup && public_key == public_key_dup) { - return UECC_SUCCESS; - } - /* Erase key in case of FI */ - mbedtls_platform_memset(public_key, 0, 2 * NUM_ECC_BYTES); - return UECC_FAULT_DETECTED; - } - } - return UECC_FAILURE; -} - -int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, - uint8_t *secret) { - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - wordcount_t num_bytes = NUM_ECC_BYTES; - int r = UECC_FAULT_DETECTED; - - /* Converting buffers to correct bit order: */ - uECC_vli_bytesToNative(_private, private_key, TC_BITS_TO_BYTES(NUM_ECC_BITS)); - uECC_vli_bytesToNative(_public, public_key, num_bytes); - uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, - num_bytes); - - r = EccPoint_mult_safer(_public, _public, _private); - uECC_vli_nativeToBytes(secret, num_bytes, _public); - - /* erasing temporary buffer used to store secret: */ - if (_private == mbedtls_platform_zeroize(_private, sizeof(_private))) { - return r; - } - - return UECC_FAULT_DETECTED; -} -#endif /* TINYCRYPT_PRIMITIVES */ +/* ec_dh.c - TinyCrypt implementation of EC-DH */ + +/* + * Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include + +int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, + unsigned int *d, uECC_Curve curve) +{ + + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + /* This function is designed for test purposes-only (such as validating NIST + * test vectors) as it uses a provided value for d instead of generating + * it uniformly at random. */ + memcpy (_private, d, NUM_ECC_BYTES); + + /* Computing public-key from private: */ + if (EccPoint_compute_public_key(_public, _private, curve)) { + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(curve->num_n_bits), + _private); + uECC_vli_nativeToBytes(public_key, + curve->num_bytes, + _public); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, + curve->num_bytes, + _public + curve->num_words); + + /* erasing temporary buffer used to store secret: */ + _set_secure(_private, 0, NUM_ECC_BYTES); + + return 1; + } + return 0; +} + +int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) +{ + + uECC_word_t _random[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _private uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + !rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) { + return 0; + } + + /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ + uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + + /* Computing public-key from private: */ + if (EccPoint_compute_public_key(_public, _private, curve)) { + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(curve->num_n_bits), + _private); + uECC_vli_nativeToBytes(public_key, + curve->num_bytes, + _public); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, + curve->num_bytes, + _public + curve->num_words); + + /* erasing temporary buffer that stored secret: */ + _set_secure(_private, 0, NUM_ECC_BYTES); + + return 1; + } + } + return 0; +} + +int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, + uint8_t *secret, uECC_Curve curve) +{ + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t *p2[2] = {_private, tmp}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + int r; + + /* Converting buffers to correct bit order: */ + uECC_vli_bytesToNative(_private, + private_key, + BITS_TO_BYTES(curve->num_n_bits)); + uECC_vli_bytesToNative(_public, + public_key, + num_bytes); + uECC_vli_bytesToNative(_public + num_words, + public_key + num_bytes, + num_bytes); + + /* Regularize the bitcount for the private key so that attackers cannot use a + * side channel attack to learn the number of leading zeros. */ + carry = regularize_k(_private, _private, tmp, curve); + + /* If an RNG function was specified, try to get a random initial Z value to + * improve protection against side-channel attacks. */ + if (uECC_get_rng()) { + if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { + r = 0; + goto clear_and_out; + } + initial_Z = p2[carry]; + } + + EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, + curve); + + uECC_vli_nativeToBytes(secret, num_bytes, _public); + r = !EccPoint_isZero(_public, curve); + +clear_and_out: + /* erasing temporary buffer used to store secret: */ + _set_secure(p2, 0, sizeof(p2)); + _set_secure(tmp, 0, sizeof(tmp)); + _set_secure(_private, 0, sizeof(_private)); + + return r; +} diff --git a/matter/mbedtls/tinycrypt/src/ecc_dsa.c b/matter/mbedtls/tinycrypt/src/ecc_dsa.c index 4e6beacdf3..06f077b478 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dsa.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dsa.c @@ -1,308 +1,290 @@ -/* ec_dsa.c - TinyCrypt implementation of EC-DSA */ - -/* - * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the - *documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "mbedtls/platform_util.h" -#include "tinycrypt/ecc.h" -#include "tinycrypt/ecc_dsa.h" - -static void bits2int(uECC_word_t *native, const uint8_t *bits, - unsigned bits_size) { - unsigned num_n_bytes = TC_BITS_TO_BYTES(NUM_ECC_BITS); - - if (bits_size > num_n_bytes) { - bits_size = num_n_bytes; - } - - uECC_vli_clear(native); - uECC_vli_bytesToNative(native, bits, bits_size); -} - -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uECC_word_t *k, uint8_t *signature) { - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t p[NUM_ECC_WORDS * 2]; - wordcount_t num_n_words = TC_BITS_TO_WORDS(NUM_ECC_BITS); - int r = UECC_FAILURE; - - /* Make sure 0 < k < curve_n */ - if (uECC_vli_isZero(k) || uECC_vli_cmp(curve_n, k) != 1) { - return UECC_FAILURE; - } - - r = EccPoint_mult_safer(p, curve_G, k); - if (r != UECC_SUCCESS) { - return r; - } - - /* If an RNG function was specified, get a random number - to prevent side channel analysis of k. */ - if (!uECC_get_rng()) { - uECC_vli_clear(tmp); - tmp[0] = 1; - } else if (uECC_generate_random_int(tmp, curve_n, num_n_words) != - UECC_SUCCESS) { - return UECC_FAILURE; - } - - /* Prevent side channel analysis of uECC_vli_modInv() to determine - bits of k / the private key by premultiplying by a random number */ - uECC_vli_modMult(k, k, tmp, curve_n); /* k' = rand * k */ - uECC_vli_modInv(k, k, curve_n); /* k = 1 / k' */ - uECC_vli_modMult(k, k, tmp, curve_n); /* k = 1 / k */ - - uECC_vli_nativeToBytes(signature, NUM_ECC_BYTES, p); /* store r */ - - /* tmp = d: */ - uECC_vli_bytesToNative(tmp, private_key, TC_BITS_TO_BYTES(NUM_ECC_BITS)); - - s[num_n_words - 1] = 0; - uECC_vli_set(s, p); - uECC_vli_modMult(s, tmp, s, curve_n); /* s = r*d */ - - bits2int(tmp, message_hash, hash_size); - uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */ - uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */ - if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) { - return UECC_FAILURE; - } - - uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s); - return r; -} - -int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uint8_t *signature) { - int r; - uECC_word_t _random[2 * NUM_ECC_WORDS]; - uECC_word_t k[NUM_ECC_WORDS]; - uECC_word_t tries; - volatile const uint8_t *private_key_dup = private_key; - volatile const uint8_t *message_hash_dup = message_hash; - volatile unsigned hash_size_dup = hash_size; - volatile uint8_t *signature_dup = signature; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _random uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != - 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - - // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): - uECC_vli_mmod(k, _random, curve_n); - - r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature); - /* don't keep trying if a fault was detected */ - if (r == UECC_FAULT_DETECTED) { - mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); - return r; - } - if (r == UECC_SUCCESS) { - if (private_key_dup != private_key || message_hash_dup != message_hash || - hash_size_dup != hash_size || signature_dup != signature) { - mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); - return UECC_FAULT_DETECTED; - } - return UECC_SUCCESS; - } - /* else keep trying */ - } - return UECC_FAILURE; -} - -static bitcount_t smax(bitcount_t a, bitcount_t b) { return (a > b ? a : b); } - -int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, - unsigned hash_size, const uint8_t *signature) { - - uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - uECC_word_t sum[NUM_ECC_WORDS * 2]; - uECC_word_t rx[NUM_ECC_WORDS]; - uECC_word_t ry[NUM_ECC_WORDS]; - uECC_word_t tx[NUM_ECC_WORDS]; - uECC_word_t ty[NUM_ECC_WORDS]; - uECC_word_t tz[NUM_ECC_WORDS]; - const uECC_word_t *points[4]; - const uECC_word_t *point; - bitcount_t num_bits; - bitcount_t i; - bitcount_t flow_control; - volatile uECC_word_t diff; - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - wordcount_t num_n_words = TC_BITS_TO_WORDS(NUM_ECC_BITS); - - rx[num_n_words - 1] = 0; - r[num_n_words - 1] = 0; - s[num_n_words - 1] = 0; - flow_control = 1; - - uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); - uECC_vli_bytesToNative(_public + num_words, public_key + NUM_ECC_BYTES, - NUM_ECC_BYTES); - uECC_vli_bytesToNative(r, signature, NUM_ECC_BYTES); - uECC_vli_bytesToNative(s, signature + NUM_ECC_BYTES, NUM_ECC_BYTES); - - /* r, s must not be 0. */ - if (uECC_vli_isZero(r) || uECC_vli_isZero(s)) { - return UECC_FAILURE; - } - - /* r, s must be < n. */ - if (uECC_vli_cmp_unsafe(curve_n, r) != 1 || - uECC_vli_cmp_unsafe(curve_n, s) != 1) { - return UECC_FAILURE; - } - - flow_control++; - - /* Calculate u1 and u2. */ - uECC_vli_modInv(z, s, curve_n); /* z = 1/s */ - u1[num_n_words - 1] = 0; - bits2int(u1, message_hash, hash_size); - uECC_vli_modMult(u1, u1, z, curve_n); /* u1 = e/s */ - uECC_vli_modMult(u2, r, z, curve_n); /* u2 = r/s */ - - /* Calculate sum = G + Q. */ - uECC_vli_set(sum, _public); - uECC_vli_set(sum + num_words, _public + num_words); - uECC_vli_set(tx, curve_G); - uECC_vli_set(ty, curve_G + num_words); - uECC_vli_modSub(z, sum, tx, curve_p); /* z = x2 - x1 */ - XYcZ_add(tx, ty, sum, sum + num_words); - uECC_vli_modInv(z, z, curve_p); /* z = 1/z */ - apply_z(sum, sum + num_words, z); - - flow_control++; - - /* Use Shamir's trick to calculate u1*G + u2*Q */ - points[0] = 0; - points[1] = curve_G; - points[2] = _public; - points[3] = sum; - num_bits = smax(uECC_vli_numBits(u1), uECC_vli_numBits(u2)); - - point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | - ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; - uECC_vli_set(rx, point); - uECC_vli_set(ry, point + num_words); - uECC_vli_clear(z); - z[0] = 1; - flow_control++; - - for (i = num_bits - 2; i >= 0; --i) { - uECC_word_t index; - double_jacobian_default(rx, ry, z); - - index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); - point = points[index]; - if (point) { - uECC_vli_set(tx, point); - uECC_vli_set(ty, point + num_words); - apply_z(tx, ty, z); - uECC_vli_modSub(tz, rx, tx, curve_p); /* Z = x2 - x1 */ - XYcZ_add(tx, ty, rx, ry); - uECC_vli_modMult_fast(z, z, tz); - } - flow_control++; - } - - uECC_vli_modInv(z, z, curve_p); /* Z = 1/Z */ - apply_z(rx, ry, z); - flow_control++; - - /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve_n, rx) != 1) { - uECC_vli_sub(rx, rx, curve_n); - } - - /* Accept only if v == r. */ - diff = uECC_vli_equal(rx, r); - if (diff == 0) { - flow_control++; - mbedtls_platform_random_delay(); - - /* Re-check the condition and test if the control flow is as expected. - * 1 (base value) + num_bits - 1 (from the loop) + 5 incrementations. - */ - if (diff == 0 && flow_control == (num_bits + 5)) { - return UECC_SUCCESS; - } else { - return UECC_FAULT_DETECTED; - } - } - - return UECC_FAILURE; -} -#endif /* TINYCRYPT_PRIMITIVES */ +/* ec_dsa.c - TinyCrypt implementation of EC-DSA */ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + + +static void bits2int(uECC_word_t *native, const uint8_t *bits, + unsigned bits_size, uECC_Curve curve) +{ + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + int shift; + uECC_word_t carry; + uECC_word_t *ptr; + + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + + uECC_vli_clear(native, num_n_words); + uECC_vli_bytesToNative(native, bits, bits_size); + if (bits_size * 8 <= (unsigned)curve->num_n_bits) { + return; + } + shift = bits_size * 8 - curve->num_n_bits; + carry = 0; + ptr = native + num_n_words; + while (ptr-- > native) { + uECC_word_t temp = *ptr; + *ptr = (temp >> shift) | carry; + carry = temp << (uECC_WORD_BITS - shift); + } + + /* Reduce mod curve_n */ + if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + uECC_vli_sub(native, native, curve->n, num_n_words); + } +} + +int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uECC_word_t *k, uint8_t *signature, + uECC_Curve curve) +{ + + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; + uECC_word_t p[NUM_ECC_WORDS * 2]; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k, num_words) || + uECC_vli_cmp(curve->n, k, num_n_words) != 1) { + return 0; + } + + carry = regularize_k(k, tmp, s, curve); + EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); + if (uECC_vli_isZero(p, num_words)) { + return 0; + } + + /* If an RNG function was specified, get a random number + to prevent side channel analysis of k. */ + if (!uECC_get_rng()) { + uECC_vli_clear(tmp, num_n_words); + tmp[0] = 1; + } + else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { + return 0; + } + + /* Prevent side channel analysis of uECC_vli_modInv() to determine + bits of k / the private key by premultiplying by a random number */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ + + uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ + + /* tmp = d: */ + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); + + s[num_n_words - 1] = 0; + uECC_vli_set(s, p, num_words); + uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + + bits2int(tmp, message_hash, hash_size, curve); + uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { + return 0; + } + + uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); + return 1; +} + +int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uint8_t *signature, uECC_Curve curve) +{ + uECC_word_t _random[2*NUM_ECC_WORDS]; + uECC_word_t k[NUM_ECC_WORDS]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _random uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) { + return 0; + } + + // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): + uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + + if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, + curve)) { + return 1; + } + } + return 0; +} + +static bitcount_t smax(bitcount_t a, bitcount_t b) +{ + return (a > b ? a : b); +} + +int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, + unsigned hash_size, const uint8_t *signature, + uECC_Curve curve) +{ + + uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + uECC_word_t sum[NUM_ECC_WORDS * 2]; + uECC_word_t rx[NUM_ECC_WORDS]; + uECC_word_t ry[NUM_ECC_WORDS]; + uECC_word_t tx[NUM_ECC_WORDS]; + uECC_word_t ty[NUM_ECC_WORDS]; + uECC_word_t tz[NUM_ECC_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes, + curve->num_bytes); + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size, curve); + uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public, num_words); + uECC_vli_set(sum + num_words, _public + num_words, num_words); + uECC_vli_set(tx, curve->G, num_words); + uECC_vli_set(ty, curve->G + num_words, num_words); + uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words, curve); + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_clear(z, num_words); + z[0] = 1; + + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + curve->double_jacobian(rx, ry, z, curve); + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point, num_words); + uECC_vli_set(ty, point + num_words, num_words); + apply_z(tx, ty, z, curve); + uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry, curve); + uECC_vli_modMult_fast(z, z, tz, curve); + } + } + + uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + apply_z(rx, ry, z, curve); + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words) == 0); +} + diff --git a/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c b/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c new file mode 100644 index 0000000000..1867988f99 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c @@ -0,0 +1,105 @@ +/* uECC_platform_specific.c - Implementation of platform specific functions*/ + +/* Copyright (c) 2014, Kenneth MacKay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE.*/ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * uECC_platform_specific.c -- Implementation of platform specific functions + */ + + +#if defined(unix) || defined(__linux__) || defined(__unix__) || \ + defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \ + defined(uECC_POSIX) + +/* Some POSIX-like system with /dev/urandom or /dev/random. */ +#include +#include +#include + +#include + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +int default_CSPRNG(uint8_t *dest, unsigned int size) { + + /* input sanity check: */ + if (dest == (uint8_t *) 0 || (size <= 0)) + return 0; + + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return 0; + } + } + + char *ptr = (char *)dest; + size_t left = (size_t) size; + while (left > 0) { + ssize_t bytes_read = read(fd, ptr, left); + if (bytes_read <= 0) { // read failed + close(fd); + return 0; + } + left -= bytes_read; + ptr += bytes_read; + } + + close(fd); + return 1; +} + +#endif /* platform */ + diff --git a/matter/mbedtls/tinycrypt/src/hmac.c b/matter/mbedtls/tinycrypt/src/hmac.c new file mode 100644 index 0000000000..cef5bf39b2 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/hmac.c @@ -0,0 +1,147 @@ +/* hmac.c - TinyCrypt implementation of the HMAC algorithm */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) +{ + const uint8_t inner_pad = (uint8_t) 0x36; + const uint8_t outer_pad = (uint8_t) 0x5c; + unsigned int i; + + for (i = 0; i < key_size; ++i) { + key[i] = inner_pad ^ new_key[i]; + key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i]; + } + for (; i < TC_SHA256_BLOCK_SIZE; ++i) { + key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad; + } +} + +int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, + unsigned int key_size) +{ + /* Input sanity check */ + if (ctx == (TCHmacState_t) 0 || + key == (const uint8_t *) 0 || + key_size == 0) { + return TC_CRYPTO_FAIL; + } + + const uint8_t dummy_key[TC_SHA256_BLOCK_SIZE]; + struct tc_hmac_state_struct dummy_state; + + if (key_size <= TC_SHA256_BLOCK_SIZE) { + /* + * The next three calls are dummy calls just to avoid + * certain timing attacks. Without these dummy calls, + * adversaries would be able to learn whether the key_size is + * greater than TC_SHA256_BLOCK_SIZE by measuring the time + * consumed in this process. + */ + (void)tc_sha256_init(&dummy_state.hash_state); + (void)tc_sha256_update(&dummy_state.hash_state, + dummy_key, + key_size); + (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE], + &dummy_state.hash_state); + + /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */ + rekey(ctx->key, key, key_size); + } else { + (void)tc_sha256_init(&ctx->hash_state); + (void)tc_sha256_update(&ctx->hash_state, key, key_size); + (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE], + &ctx->hash_state); + rekey(ctx->key, + &ctx->key[TC_SHA256_DIGEST_SIZE], + TC_SHA256_DIGEST_SIZE); + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_init(TCHmacState_t ctx) +{ + + /* input sanity check: */ + if (ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void) tc_sha256_init(&ctx->hash_state); + (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE); + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_update(TCHmacState_t ctx, + const void *data, + unsigned int data_length) +{ + + /* input sanity check: */ + if (ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void)tc_sha256_update(&ctx->hash_state, data, data_length); + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx) +{ + + /* input sanity check: */ + if (tag == (uint8_t *) 0 || + taglen != TC_SHA256_DIGEST_SIZE || + ctx == (TCHmacState_t) 0) { + return TC_CRYPTO_FAIL; + } + + (void) tc_sha256_final(tag, &ctx->hash_state); + + (void)tc_sha256_init(&ctx->hash_state); + (void)tc_sha256_update(&ctx->hash_state, + &ctx->key[TC_SHA256_BLOCK_SIZE], + TC_SHA256_BLOCK_SIZE); + (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE); + (void)tc_sha256_final(tag, &ctx->hash_state); + + /* destroy the current state */ + _set(ctx, 0, sizeof(*ctx)); + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/hmac_prng.c b/matter/mbedtls/tinycrypt/src/hmac_prng.c new file mode 100644 index 0000000000..84e7918b8c --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/hmac_prng.c @@ -0,0 +1,230 @@ +/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * min bytes in the seed string. + * MIN_SLEN*8 must be at least the expected security level. + */ +static const unsigned int MIN_SLEN = 32; + +/* + * max bytes in the seed string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_SLEN = UINT32_MAX; + +/* + * max bytes in the personalization string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_PLEN = UINT32_MAX; + +/* + * max bytes in the additional_info string; + * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). + */ +static const unsigned int MAX_ALEN = UINT32_MAX; + +/* + * max number of generates between re-seeds; + * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of + * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48. + */ +static const unsigned int MAX_GENS = UINT32_MAX; + +/* + * maximum bytes per generate call; + * SP800-90A specifies a maximum up to 2^19. + */ +static const unsigned int MAX_OUT = (1 << 19); + +/* + * Assumes: prng != NULL + */ +static void update(TCHmacPrng_t prng, const uint8_t *data, unsigned int datalen, const uint8_t *additional_data, unsigned int additional_datalen) +{ + const uint8_t separator0 = 0x00; + const uint8_t separator1 = 0x01; + + /* configure the new prng key into the prng's instance of hmac */ + tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use current state, e and separator 0 to compute a new prng key: */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0)); + + if (data && datalen) + (void)tc_hmac_update(&prng->h, data, datalen); + if (additional_data && additional_datalen) + (void)tc_hmac_update(&prng->h, additional_data, additional_datalen); + + (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); + + /* configure the new prng key into the prng's instance of hmac */ + (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use the new key to compute a new state variable v */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); + + if (data == 0 || datalen == 0) + return; + + /* configure the new prng key into the prng's instance of hmac */ + tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use current state, e and separator 1 to compute a new prng key: */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1)); + (void)tc_hmac_update(&prng->h, data, datalen); + if (additional_data && additional_datalen) + (void)tc_hmac_update(&prng->h, additional_data, additional_datalen); + (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); + + /* configure the new prng key into the prng's instance of hmac */ + (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* use the new key to compute a new state variable v */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); +} + +int tc_hmac_prng_init(TCHmacPrng_t prng, + const uint8_t *personalization, + unsigned int plen) +{ + + /* input sanity check: */ + if (prng == (TCHmacPrng_t) 0 || + personalization == (uint8_t *) 0 || + plen > MAX_PLEN) { + return TC_CRYPTO_FAIL; + } + + /* put the generator into a known state: */ + _set(prng->key, 0x00, sizeof(prng->key)); + _set(prng->v, 0x01, sizeof(prng->v)); + + update(prng, personalization, plen, 0, 0); + + /* force a reseed before allowing tc_hmac_prng_generate to succeed: */ + prng->countdown = 0; + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_prng_reseed(TCHmacPrng_t prng, + const uint8_t *seed, + unsigned int seedlen, + const uint8_t *additional_input, + unsigned int additionallen) +{ + + /* input sanity check: */ + if (prng == (TCHmacPrng_t) 0 || + seed == (const uint8_t *) 0 || + seedlen < MIN_SLEN || + seedlen > MAX_SLEN) { + return TC_CRYPTO_FAIL; + } + + if (additional_input != (const uint8_t *) 0) { + /* + * Abort if additional_input is provided but has inappropriate + * length + */ + if (additionallen == 0 || + additionallen > MAX_ALEN) { + return TC_CRYPTO_FAIL; + } else { + /* call update for the seed and additional_input */ + update(prng, seed, seedlen, additional_input, additionallen); + } + } else { + /* call update only for the seed */ + update(prng, seed, seedlen, 0, 0); + } + + /* ... and enable hmac_prng_generate */ + prng->countdown = MAX_GENS; + + return TC_CRYPTO_SUCCESS; +} + +int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) +{ + unsigned int bufferlen; + + /* input sanity check: */ + if (out == (uint8_t *) 0 || + prng == (TCHmacPrng_t) 0 || + outlen == 0 || + outlen > MAX_OUT) { + return TC_CRYPTO_FAIL; + } else if (prng->countdown == 0) { + return TC_HMAC_PRNG_RESEED_REQ; + } + + prng->countdown--; + + while (outlen != 0) { + /* configure the new prng key into the prng's instance of hmac */ + tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + + /* operate HMAC in OFB mode to create "random" outputs */ + (void)tc_hmac_init(&prng->h); + (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); + (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); + + bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ? + outlen : TC_SHA256_DIGEST_SIZE; + (void)_copy(out, bufferlen, prng->v, bufferlen); + + out += bufferlen; + outlen = (outlen > TC_SHA256_DIGEST_SIZE) ? + (outlen - TC_SHA256_DIGEST_SIZE) : 0; + } + + /* block future PRNG compromises from revealing past state */ + update(prng, 0, 0, 0, 0); + + return TC_CRYPTO_SUCCESS; +} diff --git a/matter/mbedtls/tinycrypt/src/sha256.c b/matter/mbedtls/tinycrypt/src/sha256.c new file mode 100644 index 0000000000..b4efd20445 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/sha256.c @@ -0,0 +1,217 @@ +/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void compress(unsigned int *iv, const uint8_t *data); + +int tc_sha256_init(TCSha256State_t s) +{ + /* input sanity check: */ + if (s == (TCSha256State_t) 0) { + return TC_CRYPTO_FAIL; + } + + /* + * Setting the initial state values. + * These values correspond to the first 32 bits of the fractional parts + * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17 + * and 19. + */ + _set((uint8_t *) s, 0x00, sizeof(*s)); + s->iv[0] = 0x6a09e667; + s->iv[1] = 0xbb67ae85; + s->iv[2] = 0x3c6ef372; + s->iv[3] = 0xa54ff53a; + s->iv[4] = 0x510e527f; + s->iv[5] = 0x9b05688c; + s->iv[6] = 0x1f83d9ab; + s->iv[7] = 0x5be0cd19; + + return TC_CRYPTO_SUCCESS; +} + +int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen) +{ + /* input sanity check: */ + if (s == (TCSha256State_t) 0 || + data == (void *) 0) { + return TC_CRYPTO_FAIL; + } else if (datalen == 0) { + return TC_CRYPTO_SUCCESS; + } + + while (datalen-- > 0) { + s->leftover[s->leftover_offset++] = *(data++); + if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) { + compress(s->iv, s->leftover); + s->leftover_offset = 0; + s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3); + } + } + + return TC_CRYPTO_SUCCESS; +} + +int tc_sha256_final(uint8_t *digest, TCSha256State_t s) +{ + unsigned int i; + + /* input sanity check: */ + if (digest == (uint8_t *) 0 || + s == (TCSha256State_t) 0) { + return TC_CRYPTO_FAIL; + } + + s->bits_hashed += (s->leftover_offset << 3); + + s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */ + if (s->leftover_offset > (sizeof(s->leftover) - 8)) { + /* there is not room for all the padding in this block */ + _set(s->leftover + s->leftover_offset, 0x00, + sizeof(s->leftover) - s->leftover_offset); + compress(s->iv, s->leftover); + s->leftover_offset = 0; + } + + /* add the padding and the length in big-Endian format */ + _set(s->leftover + s->leftover_offset, 0x00, + sizeof(s->leftover) - 8 - s->leftover_offset); + s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed); + s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8); + s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16); + s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24); + s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32); + s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40); + s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48); + s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56); + + /* hash the padding and length */ + compress(s->iv, s->leftover); + + /* copy the iv out to digest */ + for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) { + unsigned int t = *((unsigned int *) &s->iv[i]); + *digest++ = (uint8_t)(t >> 24); + *digest++ = (uint8_t)(t >> 16); + *digest++ = (uint8_t)(t >> 8); + *digest++ = (uint8_t)(t); + } + + /* destroy the current state */ + _set(s, 0, sizeof(*s)); + + return TC_CRYPTO_SUCCESS; +} + +/* + * Initializing SHA-256 Hash constant words K. + * These values correspond to the first 32 bits of the fractional parts of the + * cube roots of the first 64 primes between 2 and 311. + */ +static const unsigned int k256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static inline unsigned int ROTR(unsigned int a, unsigned int n) +{ + return (((a) >> n) | ((a) << (32 - n))); +} + +#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22)) +#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25)) +#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3)) +#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10)) + +#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c))) +#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))) + +static inline unsigned int BigEndian(const uint8_t **c) +{ + unsigned int n = 0; + + n = (((unsigned int)(*((*c)++))) << 24); + n |= ((unsigned int)(*((*c)++)) << 16); + n |= ((unsigned int)(*((*c)++)) << 8); + n |= ((unsigned int)(*((*c)++))); + return n; +} + +static void compress(unsigned int *iv, const uint8_t *data) +{ + unsigned int a, b, c, d, e, f, g, h; + unsigned int s0, s1; + unsigned int t1, t2; + unsigned int work_space[16]; + unsigned int n; + unsigned int i; + + a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3]; + e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7]; + + for (i = 0; i < 16; ++i) { + n = BigEndian(&data); + t1 = work_space[i] = n; + t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; + t2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + t1; + d = c; c = b; b = a; a = t1 + t2; + } + + for ( ; i < 64; ++i) { + s0 = work_space[(i+1)&0x0f]; + s0 = sigma0(s0); + s1 = work_space[(i+14)&0x0f]; + s1 = sigma1(s1); + + t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf]; + t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; + t2 = Sigma0(a) + Maj(a, b, c); + h = g; g = f; f = e; e = d + t1; + d = c; c = b; b = a; a = t1 + t2; + } + + iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d; + iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h; +} diff --git a/matter/mbedtls/tinycrypt/src/utils.c b/matter/mbedtls/tinycrypt/src/utils.c new file mode 100644 index 0000000000..13cc495123 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/utils.c @@ -0,0 +1,74 @@ +/* utils.c - TinyCrypt platform-dependent run-time operations */ + +/* + * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#define MASK_TWENTY_SEVEN 0x1b + +unsigned int _copy(uint8_t *to, unsigned int to_len, + const uint8_t *from, unsigned int from_len) +{ + if (from_len <= to_len) { + (void)memcpy(to, from, from_len); + return from_len; + } else { + return TC_CRYPTO_FAIL; + } +} + +void _set(void *to, uint8_t val, unsigned int len) +{ + (void)memset(to, val, len); +} + +/* + * Doubles the value of a byte for values up to 127. + */ +uint8_t _double_byte(uint8_t a) +{ + return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN)); +} + +int _compare(const uint8_t *a, const uint8_t *b, size_t size) +{ + const uint8_t *tempa = a; + const uint8_t *tempb = b; + uint8_t result = 0; + + for (unsigned int i = 0; i < size; i++) { + result |= tempa[i] ^ tempb[i]; + } + return result; +} From 049281bdcaa196348ca605ede5a160aca7232a34 Mon Sep 17 00:00:00 2001 From: Mathieu Kardous Date: Tue, 30 Jul 2024 15:35:17 -0400 Subject: [PATCH 03/11] WIP --- .../tinycrypt/inc/mbedtls/check_config.h | 977 ----- matter/mbedtls/tinycrypt/inc/mbedtls/config.h | 1766 --------- matter/mbedtls/tinycrypt/inc/mbedtls/oid.h | 927 ----- matter/mbedtls/tinycrypt/inc/mbedtls/pk.h | 936 ----- .../tinycrypt/inc/mbedtls/pk_internal.h | 139 - .../mbedtls/tinycrypt/inc/mbedtls/platform.h | 448 --- .../tinycrypt/inc/mbedtls/platform_util.h | 462 --- matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h | 271 +- .../mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h | 32 +- .../mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h | 41 +- .../tinycrypt/inc/tinycrypt/tinycript_util.h | 13 + .../mbedtls/tinycrypt/inc/tinycrypt/utils.h | 26 - matter/mbedtls/tinycrypt/src/cbc_mode.c | 4 +- matter/mbedtls/tinycrypt/src/cmac_mode.c | 2 +- matter/mbedtls/tinycrypt/src/ecc.c | 2191 +++++++---- matter/mbedtls/tinycrypt/src/ecc_dh.c | 240 +- matter/mbedtls/tinycrypt/src/ecc_dsa.c | 444 ++- matter/mbedtls/tinycrypt/src/hmac.c | 7 +- matter/mbedtls/tinycrypt/src/hmac_prng.c | 42 +- matter/mbedtls/tinycrypt/src/oid.c | 884 ----- matter/mbedtls/tinycrypt/src/pk.c | 641 ---- matter/mbedtls/tinycrypt/src/pk_wrap.c | 1344 ------- matter/mbedtls/tinycrypt/src/pkparse.c | 1672 --------- matter/mbedtls/tinycrypt/src/pkwrite.c | 716 ---- matter/mbedtls/tinycrypt/src/platform_util.c | 449 --- matter/mbedtls/tinycrypt/src/sha256.c | 217 -- matter/mbedtls/tinycrypt/src/tinycript_util.c | 206 ++ matter/mbedtls/tinycrypt/src/x509_crt.c | 3196 ----------------- matter/mbedtls/tinycrypt/src/x509write_csr.c | 355 -- 29 files changed, 2056 insertions(+), 16592 deletions(-) delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/check_config.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/config.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/oid.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/pk.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/pk_internal.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/platform.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/platform_util.h create mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h delete mode 100644 matter/mbedtls/tinycrypt/src/oid.c delete mode 100644 matter/mbedtls/tinycrypt/src/pk.c delete mode 100644 matter/mbedtls/tinycrypt/src/pk_wrap.c delete mode 100644 matter/mbedtls/tinycrypt/src/pkparse.c delete mode 100644 matter/mbedtls/tinycrypt/src/pkwrite.c delete mode 100644 matter/mbedtls/tinycrypt/src/platform_util.c delete mode 100644 matter/mbedtls/tinycrypt/src/sha256.c create mode 100644 matter/mbedtls/tinycrypt/src/tinycript_util.c delete mode 100644 matter/mbedtls/tinycrypt/src/x509_crt.c delete mode 100644 matter/mbedtls/tinycrypt/src/x509write_csr.c diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/check_config.h b/matter/mbedtls/tinycrypt/inc/mbedtls/check_config.h deleted file mode 100644 index 576e10eb67..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/check_config.h +++ /dev/null @@ -1,977 +0,0 @@ -/** - * \file check_config.h - * - * \brief Consistency checks for configuration options - */ -/* - * 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. - */ - -/* - * It is recommended to include this file from your config.h - * in order to catch dependency issues early. - */ - -#ifndef MBEDTLS_CHECK_CONFIG_H -#define MBEDTLS_CHECK_CONFIG_H - -/* - * We assume CHAR_BIT is 8 in many places. In practice, this is true on our - * target platforms, so not an issue, but let's just be extra sure. - */ -#include -#if CHAR_BIT != 8 -#error "mbed TLS requires a platform with 8-bit chars" -#endif - -#if defined(_WIN32) -#if !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_C is required on Windows" -#endif - -/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as - * it would confuse config.py. */ -#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif - -#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_VSNPRINTF_ALT -#endif -#endif /* _WIN32 */ - -#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) -#error \ - "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" -#endif - -#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(__GNUC__) && \ - !defined(__clang__) -#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" -#endif - -#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) -#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" -#endif - -#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_AESNI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) -#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) -#error "MBEDTLS_DHM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && \ - !defined(MBEDTLS_SSL_TRUNCATED_HMAC) -#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CMAC_C) && !defined(MBEDTLS_AES_C) && \ - !defined(MBEDTLS_DES_C) -#error "MBEDTLS_CMAC_C defined, but not all prerequisites" -#endif - -#if defined(TINYCRYPT_PRIMITIVES) && defined(MBEDTLS_NO_64BIT_MULTIPLICATION) -#error \ - "TINYCRYPT_PRIMITIVES defined, but it cannot be defined with MBEDTLS_NO_64BIT_MULTIPLICATION" -#endif -#if defined(TINYCRYPT_PRIMITIVES) && !defined(MBEDTLS_SHA256_C) -#error "TINYCRYPT_PRIMITIVES defined, but not MBEDTLS_SHA256_C" -#endif -#if defined(OPTIMIZE_TINYCRYPT_ASM) && \ - (!defined(MBEDTLS_HAVE_ASM) || !defined(TINYCRYPT_PRIMITIVES)) -#error "OPTIMIZE_TINYCRYPT_ASM defined, but not all prerequesites" -#endif - -#if defined(MBEDTLS_NIST_KW_C) && \ - (!defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C)) -#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) -#error "MBEDTLS_ECDH_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDSA_C) && \ - (!defined(MBEDTLS_ECP_C) || \ - !(defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)) || \ - !defined(MBEDTLS_ASN1_PARSE_C) || !defined(MBEDTLS_ASN1_WRITE_C)) -#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECJPAKE_C) && \ - (!defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C)) -#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RESTARTABLE) && \ - (defined(MBEDTLS_USE_PSA_CRYPTO) || \ - defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ - defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ - defined(MBEDTLS_ECDSA_SIGN_ALT) || defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ - defined(MBEDTLS_ECDSA_GENKEY_ALT) || defined(MBEDTLS_ECP_INTERNAL_ALT) || \ - defined(MBEDTLS_ECP_ALT)) -#error \ - "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" -#endif - -#if defined(MBEDTLS_ECP_RESTARTABLE) && !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) -#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT" -#endif - -#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \ - defined(MBEDTLS_ECDH_LEGACY_CONTEXT) -#error \ - "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" -#endif - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) -#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_C) && (!defined(MBEDTLS_BIGNUM_C) || \ - (!defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED))) -#error "MBEDTLS_ECP_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_C) && \ - !(defined(MBEDTLS_ECP_ALT) || defined(MBEDTLS_CTR_DRBG_C) || \ - defined(MBEDTLS_HMAC_DRBG_C) || defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) -#error \ - "MBEDTLS_ECP_C requires a DRBG module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" -#endif - -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_PKCS5_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_C) && \ - (!defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA256_C)) -#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ - defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && \ - (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && \ - (!defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256)) && \ - defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && \ - (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_ENTROPY_FORCE_SHA256) && \ - !defined(MBEDTLS_SHA256_C) -#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" -#endif - -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -#define MBEDTLS_HAS_MEMSAN -#endif -#endif -#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) -#error \ - "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" -#endif -#undef MBEDTLS_HAS_MEMSAN - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - (!defined(MBEDTLS_ENTROPY_C) || \ - !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - (defined(MBEDTLS_ENTROPY_NV_SEED) || \ - defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || defined(MBEDTLS_HAVEGE_C)) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" -#endif - -#if defined(MBEDTLS_CCM_C) && \ - (!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && \ - !defined(MBEDTLS_ARIA_C)) -#error "MBEDTLS_CCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C) -#error "MBEDTLS_CCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_GCM_C) && \ - (!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && \ - !defined(MBEDTLS_ARIA_C)) -#error "MBEDTLS_GCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C) -#error "MBEDTLS_GCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C) -#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C) -#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && \ - !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && \ - !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error \ - "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" -#endif - -#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) -#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_HKDF_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ - (!defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C)) -#error \ - "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - (!defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C)) -#error \ - "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) -#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && !defined(MBEDTLS_ECDH_C) -#error \ - "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - (!defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15)) -#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - (!defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15)) -#error \ - "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - (!defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C)) -#error \ - "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ - (!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15)) -#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - (!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15)) -#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ - (!defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)) -#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ - !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ - (!defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) && \ - !defined(MBEDTLS_SHA1_C)) -#error \ - "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" -#endif - -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY)) -#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) -#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) -#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_C) && \ - (!defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) && \ - !defined(TINYCRYPT_PRIMITIVES)) -#error "MBEDTLS_PK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS11_C) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error \ - "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning \ - "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_PKCS11_C */ - -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_EXIT) || defined(MBEDTLS_PLATFORM_EXIT_ALT)) -#error \ - "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_ALT) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME)) -#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME)) -#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME)) -#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_TIME) || defined(MBEDTLS_PLATFORM_TIME_ALT)) -#error \ - "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_TIME) || defined(MBEDTLS_PLATFORM_TIME_ALT)) -#error \ - "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_FPRINTF) || \ - defined(MBEDTLS_PLATFORM_FPRINTF_ALT)) -#error \ - "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY)) -#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && defined(MBEDTLS_PLATFORM_STD_FREE) -#error \ - "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ - !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#error \ - "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY)) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ - defined(MBEDTLS_PLATFORM_STD_CALLOC) -#error \ - "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ - !defined(MBEDTLS_PLATFORM_FREE_MACRO) -#error \ - "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_PRINTF) || \ - defined(MBEDTLS_PLATFORM_PRINTF_ALT)) -#error \ - "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_SNPRINTF) || \ - defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)) -#error \ - "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) && \ - !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_EXIT) && !defined(MBEDTLS_PLATFORM_EXIT_ALT) -#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_TIME) && \ - (!defined(MBEDTLS_PLATFORM_TIME_ALT) || !defined(MBEDTLS_HAVE_TIME)) -#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) && \ - !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_PRINTF) && \ - !defined(MBEDTLS_PLATFORM_PRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) && \ - !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) && \ - (!defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C)) -#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) && !defined(MBEDTLS_ENTROPY_NV_SEED) -#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) && \ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) && \ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) || \ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT)) -#error \ - "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) && \ - (defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) || \ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT)) -#error \ - "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) && \ - !(((defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C)) && \ - defined(MBEDTLS_ENTROPY_C)) || \ - defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)) -#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) -#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ - !(defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)) -#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && !defined(MBEDTLS_PSA_CRYPTO_C) -#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ - !(defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ - defined(MBEDTLS_ENTROPY_NV_SEED)) -#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ - !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) -#error \ - "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" -#endif - -#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ - defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) -#error \ - "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" -#endif - -#if defined(MBEDTLS_PSA_ITS_FILE_C) && !defined(MBEDTLS_FS_IO) -#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \ - defined(MBEDTLS_USE_PSA_CRYPTO) -#error \ - "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." -#endif - -#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \ - !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C) -#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \ - MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined." -#endif - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) && \ - !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PSA_CRYPTO_C) -#error "MBEDTLS_PSA_CRYPTO_C, MBEDTLS_RSA_C and MBEDTLS_PKCS1_V15 defined, \ - but not all prerequisites" -#endif - -#if defined(MBEDTLS_RSA_C) && \ - (!defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_OID_C)) -#error "MBEDTLS_RSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_RSA_C) && \ - (!defined(MBEDTLS_PKCS1_V21) && !defined(MBEDTLS_PKCS1_V15)) -#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" -#endif - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ - (!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21)) -#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) -#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && \ - (!defined(MBEDTLS_MD5_C) || !defined(MBEDTLS_SHA1_C)) -#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1) && \ - (!defined(MBEDTLS_MD5_C) || !defined(MBEDTLS_SHA1_C)) -#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - (!defined(MBEDTLS_MD5_C) || !defined(MBEDTLS_SHA1_C)) -#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - (!defined(MBEDTLS_SHA1_C) && !defined(MBEDTLS_SHA256_C) && \ - !defined(MBEDTLS_SHA512_C)) -#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && \ - (!defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_SHA256_C) && \ - !defined(MBEDTLS_SHA512_C)) -#error \ - "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL defined, but not all prerequisites" -#endif - -#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ - !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)) -#error "One or more versions of the TLS protocol are enabled " \ - "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && \ - (!defined(MBEDTLS_CIPHER_C) || !defined(MBEDTLS_MD_C)) -#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && \ - (!defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1_2)) -#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && \ - (defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && \ - (defined(MBEDTLS_SSL_PROTO_TLS1) && defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && \ - (defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - (!defined(MBEDTLS_SSL_PROTO_TLS1) || !defined(MBEDTLS_SSL_PROTO_TLS1_1))) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) -#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ - !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ - (!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS)) -#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ - (!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS)) -#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ - defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && MBEDTLS_SSL_CID_IN_LEN_MAX > 255 -#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ - defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 -#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ - (!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS)) -#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) -#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ - !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) -#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ - !defined(MBEDTLS_X509_CRT_PARSE_C) -#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_THREADING_PTHREAD) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_ALT) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_C defined, single threading implementation required" -#endif -#undef MBEDTLS_THREADING_IMPL - -#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) -#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) -#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_USE_C) && \ - (!defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_OID_C) || \ - !defined(MBEDTLS_ASN1_PARSE_C) || !defined(MBEDTLS_PK_PARSE_C)) -#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CREATE_C) && \ - (!defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_OID_C) || \ - !defined(MBEDTLS_ASN1_WRITE_C) || !defined(MBEDTLS_PK_WRITE_C)) -#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C) -#error "MBEDTLS_CERTS_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && (!defined(MBEDTLS_X509_USE_C)) -#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRL_PARSE_C) && (!defined(MBEDTLS_X509_USE_C)) -#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_PARSE_C) && (!defined(MBEDTLS_X509_USE_C)) -#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) && (!defined(MBEDTLS_X509_CREATE_C)) -#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_WRITE_C) && (!defined(MBEDTLS_X509_CREATE_C)) -#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) -#error \ - "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" -#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ - -#if (defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64)) && \ - defined(MBEDTLS_HAVE_ASM) -#error \ - "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" -#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error \ - "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning \ - "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error \ - "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning \ - "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS" -#endif -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -#if defined(MBEDTLS_DEPRECATED_REMOVED) -#error \ - "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" -#elif defined(MBEDTLS_DEPRECATED_WARNING) -#warning \ - "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS" -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -#if defined(MBEDTLS_SSL_DTLS_SRTP) && (!defined(MBEDTLS_SSL_PROTO_DTLS)) -#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && \ - (!defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)) -#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" -#endif - -/* - * Avoid warning from -pedantic. This is a convenient place for this - * workaround since this is included by every single file before the - * #if defined(MBEDTLS_xxx_C) that results in empty translation units. - */ -typedef int mbedtls_iso_c_forbids_empty_translation_units; - -#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/config.h b/matter/mbedtls/tinycrypt/inc/mbedtls/config.h deleted file mode 100644 index ce3bdbc38b..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/config.h +++ /dev/null @@ -1,1766 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -/* - * 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. - */ - -#ifndef MBEDTLS_CONFIG_H -#define MBEDTLS_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def MBEDTLS_HAVE_ASM - * - * The compiler has support for asm(). - * - * Requires support for asm() in compiler. - * - * Used in: - * library/aria.c - * library/timing.c - * include/mbedtls/bn_mul.h - * - * Required by: - * MBEDTLS_AESNI_C - * MBEDTLS_PADLOCK_C - * - * Comment to disable the use of assembly code. - */ -#define MBEDTLS_HAVE_ASM - -/** - * \def MBEDTLS_NO_UDBL_DIVISION - * - * The platform lacks support for double-width integer division (64-bit - * division on a 32-bit platform, 128-bit division on a 64-bit platform). - * - * Used in: - * include/mbedtls/bignum.h - * library/bignum.c - * - * The bignum code uses double-width division to speed up some operations. - * Double-width division is often implemented in software that needs to - * be linked with the program. The presence of a double-width integer - * type is usually detected automatically through preprocessor macros, - * but the automatic detection cannot know whether the code needs to - * and can be linked with an implementation of division for that type. - * By default division is assumed to be usable if the type is present. - * Uncomment this option to prevent the use of double-width division. - * - * Note that division for the native integer type is always required. - * Furthermore, a 64-bit type is always required even on a 32-bit - * platform, but it need not support multiplication or division. In some - * cases it is also desirable to disable some double-width operations. For - * example, if double-width division is implemented in software, disabling - * it can reduce code size in some embedded targets. - */ -//#define MBEDTLS_NO_UDBL_DIVISION - -/** - * \def MBEDTLS_NO_64BIT_MULTIPLICATION - * - * The platform lacks support for 32x32 -> 64-bit multiplication. - * - * Used in: - * library/poly1305.c - * - * Some parts of the library may use multiplication of two unsigned 32-bit - * operands with a 64-bit result in order to speed up computations. On some - * platforms, this is not available in hardware and has to be implemented in - * software, usually in a library provided by the toolchain. - * - * Sometimes it is not desirable to have to link to that library. This option - * removes the dependency of that library on platforms that lack a hardware - * 64-bit multiplier by embedding a software implementation in Mbed TLS. - * - * Note that depending on the compiler, this may decrease performance compared - * to using the library function provided by the toolchain. - */ -//#define MBEDTLS_NO_64BIT_MULTIPLICATION - -/** - * \def MBEDTLS_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - */ -//#define MBEDTLS_HAVE_SSE2 - -/** - * \def MBEDTLS_HAVE_TIME - * - * System has time.h and time(). - * The time does not need to be correct, only time differences are used, - * by contrast with MBEDTLS_HAVE_TIME_DATE - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#define MBEDTLS_HAVE_TIME - -#pragma once -/** - * \def MBEDTLS_HAVE_TIME_DATE - * - * System has time.h, time(), and an implementation for - * mbedtls_platform_gmtime_r() (see below). - * The time needs to be correct (not necessarily very accurate, but at least - * the date should be correct). This is used to verify the validity period of - * X.509 certificates. - * - * Comment if your system does not have a correct clock. - * - * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that - * behaves similarly to the gmtime_r() function from the C standard. Refer to - * the documentation for mbedtls_platform_gmtime_r() for more information. - * - * \note It is possible to configure an implementation for - * mbedtls_platform_gmtime_r() at compile-time by using the macro - * MBEDTLS_PLATFORM_GMTIME_R_ALT. - */ -#define MBEDTLS_HAVE_TIME_DATE - -#include -#include -#include -/** - * Enable FreeRTOS threading support - */ -#define MBEDTLS_FREERTOS -//#define MBEDTLS_THREADING_C -#define MBEDTLS_NO_PLATFORM_ENTROPY 1 -/** - * Enable H Crypto and Entropy modules - */ -#define MBEDTLS_AES_C -#define MBEDTLS_ECP_C -#define MBEDTLS_ECDH_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_CIPHER_MODE_CTR -#define MBEDTLS_TRNG_C - -#define MBEDTLS_TEST_NULL_ENTROPY -#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -//#define MBEDTLS_ENTROPY_NV_SEED -//#define MBEDTLS_FS_IO -//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "test" -//#define MBEDTLS_PLATFORM_NV_SEED_ALT -//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read1 -//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write1 -//#define MBEDTLS_HAVEGE_C -//#define MBEDTLS_TIMING_C -//#define MBEDTLS_TIMING_ALT - -#if defined(MBEDTLS_ECP_ALT) && !defined(MBEDTLS_ECP_RESTARTABLE) -typedef void mbedtls_ecp_restart_ctx; -#endif - -#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf - -#define MBEDTLS_AES_ROM_TABLES -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#define MBEDTLS_BASE64_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_CCM_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CIPHER_MODE_CBC -#define MBEDTLS_CIPHER_MODE_CFB -#define MBEDTLS_CIPHER_MODE_CTR -#define MBEDTLS_CMAC_C -#define MBEDTLS_CIPHER_MODE_OFB -#define MBEDTLS_CTR_DRBG_C -#define MBEDTLS_CIPHER_MODE_XTS -#define MBEDTLS_ECDH_LEGACY_CONTEXT -#define MBEDTLS_ECDSA_C -#define MBEDTLS_CIPHER_PADDING_PKCS7 -#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#define MBEDTLS_CIPHER_PADDING_ZEROS -#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES -#define MBEDTLS_ECDSA_DETERMINISTIC -#define MBEDTLS_REMOVE_3DES_CIPHERSUITES -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECJPAKE_C -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -/* Montgomery curves (supporting ECP) */ -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define MBEDTLS_ECP_DP_CURVE448_ENABLED - -/** - * \def MBEDTLS_ECP_NIST_OPTIM - * - * Enable specific 'modulo p' routines for each NIST prime. - * Depending on the prime and architecture, makes operations 4 to 8 times - * faster on the corresponding curve. - * - * Comment this macro to disable NIST curves optimisation. - */ -#define MBEDTLS_ECP_NIST_OPTIM -#define MBEDTLS_ENTROPY_FORCE_SHA256 -// TODO: 3R -// #define MBEDTLS_ENTROPY_HARDWARE_ALT - -#define MBEDTLS_ECDH_LEGACY_CONTEXT -#define MBEDTLS_ERROR_STRERROR_DUMMY -#define MBEDTLS_ECDSA_DETERMINISTIC -#define MBEDTLS_HAVE_ASM -#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#define MBEDTLS_HKDF_C -#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#define MBEDTLS_PK_PARSE_EC_EXTENDED -#define MBEDTLS_ERROR_STRERROR_DUMMY -#define MBEDTLS_GENPRIME -#define MBEDTLS_MD_C -#define MBEDTLS_FS_IO -#define MBEDTLS_OID_C -#define MBEDTLS_PEM_PARSE_C -#define MBEDTLS_PEM_WRITE_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PK_RSA_ALT_SUPPORT -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PKCS1_V15 -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PKCS1_V21 -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_PLATFORM_MEMORY -//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -//#define MBEDTLS_PSA_CRYPTO_C -#define MBEDTLS_PSA_CRYPTO_CONFIG -//#define MBEDTLS_PSA_CRYPTO_DRIVERS -//#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS -//#define MBEDTLS_PSA_CRYPTO_STORAGE_C -#define MBEDTLS_SELF_TEST -#define MBEDTLS_SHA256_SMALLER -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_ALL_ALERT_MESSAGES -#define MBEDTLS_SSL_RECORD_CHECKING -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_COOKIE_C -#define MBEDTLS_SSL_DTLS_ANTI_REPLAY -#define MBEDTLS_SSL_CONTEXT_SERIALIZATION -#define MBEDTLS_SSL_DTLS_HELLO_VERIFY -#define MBEDTLS_SSL_ENCRYPT_THEN_MAC -#define MBEDTLS_SSL_EXPORT_KEYS -#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET -#define MBEDTLS_SSL_FALLBACK_SCSV -#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING -#define MBEDTLS_SSL_RENEGOTIATION -#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define MBEDTLS_SSL_PROTO_TLS1 -#define MBEDTLS_SSL_PROTO_TLS1_1 -#define MBEDTLS_SSL_PROTO_TLS1_2 -#define MBEDTLS_SSL_PROTO_DTLS -#define MBEDTLS_SSL_ALPN -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C -#define MBEDTLS_SSL_DTLS_ANTI_REPLAY -#define MBEDTLS_X509_CREATE_C -#define MBEDTLS_SSL_DTLS_HELLO_VERIFY -#define MBEDTLS_X509_CSR_WRITE_C -#define MBEDTLS_X509_CRL_PARSE_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_CSR_PARSE_C -#define MBEDTLS_X509_USE_C - -#define MBEDTLS_MPI_WINDOW_SIZE 1 /**< Maximum windows size used. */ -#define MBEDTLS_MPI_MAX_SIZE \ - 32 /**< Maximum number of bytes for usable MPIs. \ - */ -//#define MBEDTLS_ECP_MAX_BITS 256 /**< Maximum bit size of groups */ -#define MBEDTLS_ECP_WINDOW_SIZE 2 /**< Maximum window size used */ -#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */ -#define MBEDTLS_ENTROPY_MAX_SOURCES \ - 2 /**< Maximum number of sources supported */ -#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT -#define MBEDTLS_SSL_MAX_CONTENT_LEN \ - 900 /**< Maxium fragment length in bytes \ - */ - -#define MBEDTLS_SSL_SESSION_TICKETS -#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 - -//#include "config-device-acceleration.h" -#include "mbedtls/check_config.h" - -#define MBEDTLS_SSL_EXPORT_KEYS -#define MBEDTLS_SSL_SERVER_NAME_INDICATION -#define MBEDTLS_SSL_TRUNCATED_HMAC -#define MBEDTLS_VERSION_FEATURES -#define MBEDTLS_X509_CHECK_KEY_USAGE -#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#define MBEDTLS_X509_RSASSA_PSS_SUPPORT -#define MBEDTLS_AESNI_C -#define MBEDTLS_AES_C -#define MBEDTLS_ARC4_C -#define MBEDTLS_ASN1_PARSE_C -#define MBEDTLS_ASN1_WRITE_C -#define MBEDTLS_BASE64_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_BLOWFISH_C -#define MBEDTLS_CAMELLIA_C -#define MBEDTLS_CCM_C -#define MBEDTLS_CERTS_C -#define MBEDTLS_CHACHA20_C -#define MBEDTLS_CHACHAPOLY_C -#define MBEDTLS_CIPHER_C -#define MBEDTLS_CTR_DRBG_C -#define MBEDTLS_DEBUG_C -#define MBEDTLS_DES_C -#define MBEDTLS_DHM_C -#define MBEDTLS_ECDH_C -#define MBEDTLS_ECDSA_C -#define MBEDTLS_ECP_C -#define MBEDTLS_ENTROPY_C -#define MBEDTLS_ERROR_C -#define MBEDTLS_GCM_C -#define MBEDTLS_HKDF_C -#define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_MD_C -#define MBEDTLS_MD5_C -#define MBEDTLS_NET_C -#define MBEDTLS_OID_C -#define MBEDTLS_PADLOCK_C -#define MBEDTLS_PEM_PARSE_C -#define MBEDTLS_PEM_WRITE_C -#define MBEDTLS_PK_C -#define MBEDTLS_PK_PARSE_C -#define MBEDTLS_PK_WRITE_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PKCS12_C -#define MBEDTLS_PLATFORM_C -#define MBEDTLS_POLY1305_C -#define MBEDTLS_PSA_CRYPTO_C -#define MBEDTLS_PSA_CRYPTO_STORAGE_C -#define MBEDTLS_PSA_ITS_FILE_C -#define MBEDTLS_RIPEMD160_C -#define MBEDTLS_RSA_C -#define MBEDTLS_SHA1_C -#define MBEDTLS_SHA256_C -#define MBEDTLS_SHA512_C -#define MBEDTLS_SSL_CACHE_C -#define MBEDTLS_SSL_COOKIE_C -#define MBEDTLS_SSL_TICKET_C -#define MBEDTLS_SSL_CLI_C -#define MBEDTLS_SSL_SRV_C -#define MBEDTLS_SSL_TLS_C -#define MBEDTLS_TIMING_C -#define MBEDTLS_VERSION_C -#define MBEDTLS_X509_USE_C -#define MBEDTLS_X509_CRT_PARSE_C -#define MBEDTLS_X509_CRL_PARSE_C -#define MBEDTLS_X509_CSR_PARSE_C -#define MBEDTLS_X509_CREATE_C -#define MBEDTLS_X509_CRT_WRITE_C -#define MBEDTLS_X509_CSR_WRITE_C -#define MBEDTLS_XTEA_C -#if defined(MBEDTLS_USER_CONFIG_FILE) -#include MBEDTLS_USER_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) -#include "mbedtls/config_psa.h" -#endif - -#include "mbedtls/check_config.h" - -#endif /* MBEDTLS_CONFIG_H */ -#define MBEDTLS_ECP_C - -/** - * \def MBEDTLS_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C - * - * This module provides a generic entropy pool - */ -#define MBEDTLS_ENTROPY_C - -/** - * \def MBEDTLS_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables mbedtls_strerror(). - */ -#define MBEDTLS_ERROR_C - -/** - * \def MBEDTLS_GCM_C - * - * Enable the Galois/Counter Mode (GCM). - * - * Module: library/gcm.c - * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C - * - * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other - * requisites are enabled as well. - */ -#define MBEDTLS_GCM_C - -/** - * \def MBEDTLS_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments - * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. - * - * Module: library/havege.c - * Caller: - * - * Requires: MBEDTLS_TIMING_C - * - * Uncomment to enable the HAVEGE random generator. - */ -//#define MBEDTLS_HAVEGE_C - -/** - * \def MBEDTLS_HKDF_C - * - * Enable the HKDF algorithm (RFC 5869). - * - * Module: library/hkdf.c - * Caller: - * - * Requires: MBEDTLS_MD_C - * - * This module adds support for the Hashed Message Authentication Code - * (HMAC)-based key derivation function (HKDF). - */ -#define MBEDTLS_HKDF_C - -/** - * \def MBEDTLS_HMAC_DRBG_C - * - * Enable the HMAC_DRBG random generator. - * - * Module: library/hmac_drbg.c - * Caller: - * - * Requires: MBEDTLS_MD_C - * - * Uncomment to enable the HMAC_DRBG random number geerator. - */ -#define MBEDTLS_HMAC_DRBG_C - -/** - * \def MBEDTLS_NIST_KW_C - * - * Enable the Key Wrapping mode for 128-bit block ciphers, - * as defined in NIST SP 800-38F. Only KW and KWP modes - * are supported. At the moment, only AES is approved by NIST. - * - * Module: library/nist_kw.c - * - * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C - */ -//#define MBEDTLS_NIST_KW_C - -/** - * \def MBEDTLS_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define MBEDTLS_MD_C - -/** - * \def MBEDTLS_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - * - * \warning MD2 is considered a weak message digest and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger message digests instead. - * - */ -//#define MBEDTLS_MD2_C - -/** - * \def MBEDTLS_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - * - * \warning MD4 is considered a weak message digest and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger message digests instead. - * - */ -//#define MBEDTLS_MD4_C - -/** - * \def MBEDTLS_MD5_C - * - * Enable the MD5 hash algorithm. - * - * Module: library/md5.c - * Caller: library/md.c - * library/pem.c - * library/ssl_tls.c - * - * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 - * depending on the handshake parameters. Further, it is used for checking - * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded - * encrypted keys. - * - * \warning MD5 is considered a weak message digest and its use constitutes a - * security risk. If possible, we recommend avoiding dependencies on - * it, and considering stronger message digests instead. - * - */ -#define MBEDTLS_MD5_C - -/** - * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C - * - * Enable the buffer allocator implementation that makes use of a (stack) - * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() - * calls) - * - * Module: library/memory_buffer_alloc.c - * - * Requires: MBEDTLS_PLATFORM_C - * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) - * - * Enable this module to enable the buffer memory allocator. - */ -//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C - -/** - * \def MBEDTLS_NET_C - * - * Enable the TCP and UDP over IPv6/IPv4 networking routines. - * - * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) - * and Windows. For other platforms, you'll want to disable it, and write your - * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). - * - * \note See also our Knowledge Base article about porting to a new - * environment: - * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS - * - * Module: library/net_sockets.c - * - * This module provides networking routines. - */ -#define MBEDTLS_NET_C - -/** - * \def MBEDTLS_OID_C - * - * Enable the OID database. - * - * Module: library/oid.c - * Caller: library/asn1write.c - * library/pkcs5.c - * library/pkparse.c - * library/pkwrite.c - * library/rsa.c - * library/x509.c - * library/x509_create.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * This modules translates between OIDs and internal values. - */ -#define MBEDTLS_OID_C - -/** - * \def MBEDTLS_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * Requires: MBEDTLS_HAVE_ASM - * - * This modules adds support for the VIA PadLock on x86. - */ -#define MBEDTLS_PADLOCK_C - -/** - * \def MBEDTLS_PEM_PARSE_C - * - * Enable PEM decoding / parsing. - * - * Module: library/pem.c - * Caller: library/dhm.c - * library/pkparse.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_BASE64_C - * - * This modules adds support for decoding / parsing PEM files. - */ -#define MBEDTLS_PEM_PARSE_C - -/** - * \def MBEDTLS_PEM_WRITE_C - * - * Enable PEM encoding / writing. - * - * Module: library/pem.c - * Caller: library/pkwrite.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * Requires: MBEDTLS_BASE64_C - * - * This modules adds support for encoding / writing PEM files. - */ -#define MBEDTLS_PEM_WRITE_C - -/** - * \def MBEDTLS_PK_C - * - * Enable the generic public (asymmetric) key layer. - * - * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C - * - * Uncomment to enable generic public key wrappers. - */ -#define MBEDTLS_PK_C - -/** - * \def MBEDTLS_PK_PARSE_C - * - * Enable the generic public (asymmetric) key parser. - * - * Module: library/pkparse.c - * Caller: library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_PK_C - * - * Uncomment to enable generic public key parse functions. - */ -#define MBEDTLS_PK_PARSE_C - -/** - * \def MBEDTLS_PK_WRITE_C - * - * Enable the generic public (asymmetric) key writer. - * - * Module: library/pkwrite.c - * Caller: library/x509write.c - * - * Requires: MBEDTLS_PK_C - * - * Uncomment to enable generic public key write functions. - */ -#define MBEDTLS_PK_WRITE_C - -/** - * \def MBEDTLS_PKCS5_C - * - * Enable PKCS#5 functions. - * - * Module: library/pkcs5.c - * - * Requires: MBEDTLS_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define MBEDTLS_PKCS5_C - -/** - * \def MBEDTLS_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support via the pkcs11-helper library. - * - * \deprecated This option is deprecated and will be removed in a future - * version of Mbed TLS. - * - * Module: library/pkcs11.c - * Caller: library/pk.c - * - * Requires: MBEDTLS_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) - */ -//#define MBEDTLS_PKCS11_C - -/** - * \def MBEDTLS_PKCS12_C - * - * Enable PKCS#12 PBE functions. - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/pkparse.c - * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C - * Can use: MBEDTLS_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define MBEDTLS_PKCS12_C - -/** - * \def MBEDTLS_PLATFORM_C - * - * Enable the platform abstraction layer that allows you to re-assign - * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). - * - * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT - * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned - * above to be specified at runtime or compile time respectively. - * - * \note This abstraction layer must be enabled on Windows (including MSYS2) - * as other module rely on it for a fixed snprintf implementation. - * - * Module: library/platform.c - * Caller: Most other .c files - * - * This module enables abstraction of common (libc) functions. - */ -#define MBEDTLS_PLATFORM_C - -/** - * \def MBEDTLS_POLY1305_C - * - * Enable the Poly1305 MAC algorithm. - * - * Module: library/poly1305.c - * Caller: library/chachapoly.c - */ -#define MBEDTLS_POLY1305_C - -/** - * \def MBEDTLS_PSA_CRYPTO_C - * - * Enable the Platform Security Architecture cryptography API. - * - * Module: library/psa_crypto.c - * - * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C, - * or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C, - * or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. - * - */ -#define MBEDTLS_PSA_CRYPTO_C - -/** - * \def MBEDTLS_PSA_CRYPTO_SE_C - * - * Enable secure element support in the Platform Security Architecture - * cryptography API. - * - * \warning This feature is not yet suitable for production. It is provided - * for API evaluation and testing purposes only. - * - * Module: library/psa_crypto_se.c - * - * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C - * - */ -//#define MBEDTLS_PSA_CRYPTO_SE_C - -/** - * \def MBEDTLS_PSA_CRYPTO_STORAGE_C - * - * Enable the Platform Security Architecture persistent key storage. - * - * Module: library/psa_crypto_storage.c - * - * Requires: MBEDTLS_PSA_CRYPTO_C, - * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of - * the PSA ITS interface - */ -#define MBEDTLS_PSA_CRYPTO_STORAGE_C - -/** - * \def MBEDTLS_PSA_ITS_FILE_C - * - * Enable the emulation of the Platform Security Architecture - * Internal Trusted Storage (PSA ITS) over files. - * - * Module: library/psa_its_file.c - * - * Requires: MBEDTLS_FS_IO - */ -#define MBEDTLS_PSA_ITS_FILE_C - -/** - * \def MBEDTLS_RIPEMD160_C - * - * Enable the RIPEMD-160 hash algorithm. - * - * Module: library/ripemd160.c - * Caller: library/md.c - * - */ -#define MBEDTLS_RIPEMD160_C - -/** - * \def MBEDTLS_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * library/rsa_internal.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is used by the following key exchanges: - * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK - * - * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C - */ -#define MBEDTLS_RSA_C - -/** - * \def MBEDTLS_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 - * depending on the handshake parameters, and for SHA1-signed certificates. - * - * \warning SHA-1 is considered a weak message digest and its use constitutes - * a security risk. If possible, we recommend avoiding dependencies - * on it, and considering stronger message digests instead. - * - */ -#define MBEDTLS_SHA1_C - -/** - * \def MBEDTLS_SHA256_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * - * Module: library/sha256.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define MBEDTLS_SHA256_C - -/** - * \def MBEDTLS_SHA512_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * - * Module: library/sha512.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define MBEDTLS_SHA512_C - -/** - * \def MBEDTLS_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: MBEDTLS_SSL_CACHE_C - */ -#define MBEDTLS_SSL_CACHE_C - -/** - * \def MBEDTLS_SSL_COOKIE_C - * - * Enable basic implementation of DTLS cookies for hello verification. - * - * Module: library/ssl_cookie.c - * Caller: - */ -#define MBEDTLS_SSL_COOKIE_C - -/** - * \def MBEDTLS_SSL_TICKET_C - * - * Enable an implementation of TLS server-side callbacks for session tickets. - * - * Module: library/ssl_ticket.c - * Caller: - * - * Requires: MBEDTLS_CIPHER_C - */ -#define MBEDTLS_SSL_TICKET_C - -/** - * \def MBEDTLS_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: MBEDTLS_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define MBEDTLS_SSL_CLI_C - -/** - * \def MBEDTLS_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: MBEDTLS_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -#define MBEDTLS_SSL_SRV_C - -/** - * \def MBEDTLS_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C - * and at least one of the MBEDTLS_SSL_PROTO_XXX defines - * - * This module is required for SSL/TLS. - */ -#define MBEDTLS_SSL_TLS_C - -/** - * \def MBEDTLS_THREADING_C - * - * Enable the threading abstraction layer. - * By default mbed TLS assumes it is used in a non-threaded environment or that - * contexts are not shared between threads. If you do intend to use contexts - * between threads, you will need to enable this layer to prevent race - * conditions. See also our Knowledge Base article about threading: - * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading - * - * Module: library/threading.c - * - * This allows different threading implementations (self-implemented or - * provided). - * - * You will have to enable either MBEDTLS_THREADING_ALT or - * MBEDTLS_THREADING_PTHREAD. - * - * Enable this layer to allow use of mutexes within mbed TLS - */ -//#define MBEDTLS_THREADING_C - -/** - * \def MBEDTLS_TIMING_C - * - * Enable the semi-portable timing interface. - * - * \note The provided implementation only works on POSIX/Unix (including Linux, - * BSD and OS X) and Windows. On other platforms, you can either disable that - * module and provide your own implementations of the callbacks needed by - * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide - * your own implementation of the whole module by setting - * \c MBEDTLS_TIMING_ALT in the current file. - * - * \note The timing module will include time.h on suitable platforms - * regardless of the setting of MBEDTLS_HAVE_TIME, unless - * MBEDTLS_TIMING_ALT is used. See timing.c for more information. - * - * \note See also our Knowledge Base article about porting to a new - * environment: - * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -#define MBEDTLS_TIMING_C - -/** - * \def MBEDTLS_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define MBEDTLS_VERSION_C - -/** - * \def MBEDTLS_X509_USE_C - * - * Enable X.509 core for using certificates. - * - * Module: library/x509.c - * Caller: library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, - * MBEDTLS_PK_PARSE_C - * - * This module is required for the X.509 parsing modules. - */ -#define MBEDTLS_X509_USE_C - -/** - * \def MBEDTLS_X509_CRT_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is required for X.509 certificate parsing. - */ -#define MBEDTLS_X509_CRT_PARSE_C - -/** - * \def MBEDTLS_X509_CRL_PARSE_C - * - * Enable X.509 CRL parsing. - * - * Module: library/x509_crl.c - * Caller: library/x509_crt.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is required for X.509 CRL parsing. - */ -#define MBEDTLS_X509_CRL_PARSE_C - -/** - * \def MBEDTLS_X509_CSR_PARSE_C - * - * Enable X.509 Certificate Signing Request (CSR) parsing. - * - * Module: library/x509_csr.c - * Caller: library/x509_crt_write.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is used for reading X.509 certificate request. - */ -#define MBEDTLS_X509_CSR_PARSE_C - -/** - * \def MBEDTLS_X509_CREATE_C - * - * Enable X.509 core for creating certificates. - * - * Module: library/x509_create.c - * - * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C - * - * This module is the basis for creating X.509 certificates and CSRs. - */ -#define MBEDTLS_X509_CREATE_C - -/** - * \def MBEDTLS_X509_CRT_WRITE_C - * - * Enable creating X.509 certificates. - * - * Module: library/x509_crt_write.c - * - * Requires: MBEDTLS_X509_CREATE_C - * - * This module is required for X.509 certificate creation. - */ -#define MBEDTLS_X509_CRT_WRITE_C - -/** - * \def MBEDTLS_X509_CSR_WRITE_C - * - * Enable creating X.509 Certificate Signing Requests (CSR). - * - * Module: library/x509_csr_write.c - * - * Requires: MBEDTLS_X509_CREATE_C - * - * This module is required for X.509 certificate request writing. - */ -#define MBEDTLS_X509_CSR_WRITE_C - -/** - * \def MBEDTLS_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#define MBEDTLS_XTEA_C - -/** \} name SECTION: mbed TLS modules */ - -/** - * \name SECTION: General configuration options - * - * This section contains Mbed TLS build settings that are not associated - * with a particular module. - * - * \{ - */ - -/** - * \def MBEDTLS_CONFIG_FILE - * - * If defined, this is a header which will be included instead of - * `"mbedtls/config.h"`. - * This header file specifies the compile-time configuration of Mbed TLS. - * Unlike other configuration options, this one must be defined on the - * compiler command line: a definition in `config.h` would have no effect. - * - * This macro is expanded after an \#include directive. This is a - * popular but non-standard feature of the C language, so this feature is only - * available with compilers that perform macro expansion on an - * \#include line. - * - * The value of this symbol is typically a path in double quotes, either - * absolute or relative to a directory on the include search path. - */ -//#define MBEDTLS_CONFIG_FILE "mbedtls/config.h" - -/** - * \def MBEDTLS_USER_CONFIG_FILE - * - * If defined, this is a header which will be included after - * `"mbedtls/config.h"` or #MBEDTLS_CONFIG_FILE. - * This allows you to modify the default configuration, including the ability - * to undefine options that are enabled by default. - * - * This macro is expanded after an \#include directive. This is a - * popular but non-standard feature of the C language, so this feature is only - * available with compilers that perform macro expansion on an - * \#include line. - * - * The value of this symbol is typically a path in double quotes, either - * absolute or relative to a directory on the include search path. - */ -//#define MBEDTLS_USER_CONFIG_FILE "/dev/null" - -/** - * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE - * - * If defined, this is a header which will be included instead of - * `"psa/crypto_config.h"`. - * This header file specifies which cryptographic mechanisms are available - * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and - * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled. - * - * This macro is expanded after an \#include directive. This is a - * popular but non-standard feature of the C language, so this feature is only - * available with compilers that perform macro expansion on an - * \#include line. - * - * The value of this symbol is typically a path in double quotes, either - * absolute or relative to a directory on the include search path. - */ -//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h" - -/** - * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE - * - * If defined, this is a header which will be included after - * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE. - * This allows you to modify the default configuration, including the ability - * to undefine options that are enabled by default. - * - * This macro is expanded after an \#include directive. This is a - * popular but non-standard feature of the C language, so this feature is only - * available with compilers that perform macro expansion on an - * \#include line. - * - * The value of this symbol is typically a path in double quotes, either - * absolute or relative to a directory on the include search path. - */ -//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null" - -/** \} name SECTION: General configuration options */ - -/** - * \name SECTION: Module configuration options - * - * This section allows for the setting of module specific sizes and - * configuration options. The default values are already present in the - * relevant header files and should suffice for the regular use cases. - * - * Our advice is to enable options and change their values here - * only if you have a good reason and know the consequences. - * \{ - */ -/* The Doxygen documentation here is used when a user comments out a - * setting and runs doxygen themselves. On the other hand, when we typeset - * the full documentation including disabled settings, the documentation - * in specific modules' header files is used if present. When editing this - * file, make sure that each option is documented in exactly one place, - * plus optionally a same-line Doxygen comment here if there is a Doxygen - * comment in the specific module. */ - -/* MPI / BIGNUM options */ -//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ -//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for -// usable MPIs. */ - -/* CTR_DRBG options */ -//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy -// used per seed by default (48 with SHA-512, 32 with SHA-256) */ #define -// MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is -// performed by default */ #define MBEDTLS_CTR_DRBG_MAX_INPUT 256 -///**< Maximum number of additional input bytes */ #define -// MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of -// requested bytes per call */ #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< -// Maximum size of (re)seed buffer */ - -/* HMAC_DRBG options */ -//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed -// is performed by default */ #define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 -///**< Maximum number of additional input bytes */ #define -// MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested -// bytes per call */ #define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< -// Maximum size of (re)seed buffer */ - -/* ECP options */ -//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups. -// Normally determined automatically from the configured curves. */ #define -// MBEDTLS_ECP_WINDOW_SIZE 4 /**< Maximum window size used */ #define -// MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ - -/* Entropy options */ -//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of -// sources supported */ #define MBEDTLS_ENTROPY_MAX_GATHER 128 -///**< Maximum amount requested from entropy sources */ #define -// MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of -// bytes required for the hardware entropy source mbedtls_hardware_poll() before -// entropy is released */ - -/* Memory buffer allocator options */ -//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this -// value */ - -/* Platform options */ -//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if -// MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is -// needed. */ #define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default -// allocator to use, can be undefined */ #define MBEDTLS_PLATFORM_STD_FREE free -///**< Default free to use, can be undefined */ #define -// MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be -// undefined */ #define MBEDTLS_PLATFORM_STD_TIME time /**< Default -// time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ #define -// MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be -// undefined */ #define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default -// printf to use, can be undefined */ -/* Note: your snprintf must correctly zero-terminate the buffer! */ -//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to -// use, can be undefined */ #define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 -///**< Default exit value to use, can be undefined */ #define -// MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can -// be undefined */ #define MBEDTLS_PLATFORM_STD_NV_SEED_READ -// mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, -// can be undefined */ #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE -// mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to -// use, can be undefined */ #define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" -// /**< Seed file to read/write with default implementation */ - -/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ -/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be - * defined */ -//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator -// macro to use, can be undefined */ #define MBEDTLS_PLATFORM_FREE_MACRO free -///**< Default free macro to use, can be undefined */ #define -// MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, -// can be undefined */ #define MBEDTLS_PLATFORM_TIME_MACRO time /**< -// Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be -// enabled -//*/ #define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time -// macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ #define -// MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to -// use, can be undefined */ #define MBEDTLS_PLATFORM_PRINTF_MACRO printf -// /**< Default printf macro to use, can be undefined */ -/* Note: your snprintf must correctly zero-terminate the buffer! */ -//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf -// macro to use, can be undefined */ #define MBEDTLS_PLATFORM_VSNPRINTF_MACRO -// vsnprintf /**< Default vsnprintf macro to use, can be undefined */ #define -// MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< -// Default nv_seed_read function to use, can be undefined */ #define -// MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< -// Default nv_seed_write function to use, can be undefined */ - -/** - * \brief This macro is invoked by the library when an invalid parameter - * is detected that is only checked with #MBEDTLS_CHECK_PARAMS - * (see the documentation of that option for context). - * - * When you leave this undefined here, the library provides - * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT - * is defined, the default definition is `assert(cond)`, - * otherwise the default definition calls a function - * mbedtls_param_failed(). This function is declared in - * `platform_util.h` for the benefit of the library, but - * you need to define in your application. - * - * When you define this here, this replaces the default - * definition in platform_util.h (which no longer declares the - * function mbedtls_param_failed()) and it is your responsibility - * to make sure this macro expands to something suitable (in - * particular, that all the necessary declarations are visible - * from within the library - you can ensure that by providing - * them in this file next to the macro definition). - * If you define this macro to call `assert`, also define - * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files - * include ``. - * - * Note that you may define this macro to expand to nothing, in - * which case you don't have to worry about declarations or - * definitions. However, you will then be notified about invalid - * parameters only in non-void functions, and void function will - * just silently return early on invalid parameters, which - * partially negates the benefits of enabling - * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. - * - * \param cond The expression that should evaluate to true, but doesn't. - */ -//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) - -/** \def MBEDTLS_CHECK_RETURN - * - * This macro is used at the beginning of the declaration of a function - * to indicate that its return value should be checked. It should - * instruct the compiler to emit a warning or an error if the function - * is called without checking its return value. - * - * There is a default implementation for popular compilers in platform_util.h. - * You can override the default implementation by defining your own here. - * - * If the implementation here is empty, this will effectively disable the - * checking of functions' return values. - */ -//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) - -/** \def MBEDTLS_IGNORE_RETURN - * - * This macro requires one argument, which should be a C function call. - * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this - * warning is suppressed. - */ -//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result)) - -/* PSA options */ -/** - * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the - * PSA crypto subsystem. - * - * If this option is unset: - * - If CTR_DRBG is available, the PSA subsystem uses it rather than HMAC_DRBG. - * - Otherwise, the PSA subsystem uses HMAC_DRBG with either - * #MBEDTLS_MD_SHA512 or #MBEDTLS_MD_SHA256 based on availability and - * on unspecified heuristics. - */ -//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 - -/** \def MBEDTLS_PSA_KEY_SLOT_COUNT - * Restrict the PSA library to supporting a maximum amount of simultaneously - * loaded keys. A loaded key is a key stored by the PSA Crypto core as a - * volatile key, or a persistent key which is loaded temporarily by the - * library as part of a crypto operation in flight. - * - * If this option is unset, the library will fall back to a default value of - * 32 keys. - */ -//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 - -/* SSL Cache options */ -//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ -//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in -// cache */ - -/* SSL options */ - -/** \def MBEDTLS_SSL_MAX_CONTENT_LEN - * - * Maximum length (in bytes) of incoming and outgoing plaintext fragments. - * - * This determines the size of both the incoming and outgoing TLS I/O buffers - * in such a way that both are capable of holding the specified amount of - * plaintext data, regardless of the protection mechanism used. - * - * To configure incoming and outgoing I/O buffers separately, use - * #MBEDTLS_SSL_IN_CONTENT_LEN and #MBEDTLS_SSL_OUT_CONTENT_LEN, - * which overwrite the value set by this option. - * - * \note When using a value less than the default of 16KB on the client, it is - * recommended to use the Maximum Fragment Length (MFL) extension to - * inform the server about this limitation. On the server, there - * is no supported, standardized way of informing the client about - * restriction on the maximum size of incoming messages, and unless - * the limitation has been communicated by other means, it is recommended - * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN - * while keeping the default value of 16KB for the incoming buffer. - * - * Uncomment to set the maximum plaintext size of both - * incoming and outgoing I/O buffers. - */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 - -/** \def MBEDTLS_SSL_IN_CONTENT_LEN - * - * Maximum length (in bytes) of incoming plaintext fragments. - * - * This determines the size of the incoming TLS I/O buffer in such a way - * that it is capable of holding the specified amount of plaintext data, - * regardless of the protection mechanism used. - * - * If this option is undefined, it inherits its value from - * #MBEDTLS_SSL_MAX_CONTENT_LEN. - * - * \note When using a value less than the default of 16KB on the client, it is - * recommended to use the Maximum Fragment Length (MFL) extension to - * inform the server about this limitation. On the server, there - * is no supported, standardized way of informing the client about - * restriction on the maximum size of incoming messages, and unless - * the limitation has been communicated by other means, it is recommended - * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN - * while keeping the default value of 16KB for the incoming buffer. - * - * Uncomment to set the maximum plaintext size of the incoming I/O buffer - * independently of the outgoing I/O buffer. - */ -//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 - -/** \def MBEDTLS_SSL_CID_IN_LEN_MAX - * - * The maximum length of CIDs used for incoming DTLS messages. - * - */ -//#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 - -/** \def MBEDTLS_SSL_CID_OUT_LEN_MAX - * - * The maximum length of CIDs used for outgoing DTLS messages. - * - */ -//#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 - -/** \def MBEDTLS_SSL_CID_PADDING_GRANULARITY - * - * This option controls the use of record plaintext padding - * when using the Connection ID extension in DTLS 1.2. - * - * The padding will always be chosen so that the length of the - * padded plaintext is a multiple of the value of this option. - * - * Note: A value of \c 1 means that no padding will be used - * for outgoing records. - * - * Note: On systems lacking division instructions, - * a power of two should be preferred. - * - */ -//#define MBEDTLS_SSL_CID_PADDING_GRANULARITY 16 - -/** \def MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY - * - * This option controls the use of record plaintext padding - * in TLS 1.3. - * - * The padding will always be chosen so that the length of the - * padded plaintext is a multiple of the value of this option. - * - * Note: A value of \c 1 means that no padding will be used - * for outgoing records. - * - * Note: On systems lacking division instructions, - * a power of two should be preferred. - */ -//#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1 - -/** \def MBEDTLS_SSL_OUT_CONTENT_LEN - * - * Maximum length (in bytes) of outgoing plaintext fragments. - * - * This determines the size of the outgoing TLS I/O buffer in such a way - * that it is capable of holding the specified amount of plaintext data, - * regardless of the protection mechanism used. - * - * If this option undefined, it inherits its value from - * #MBEDTLS_SSL_MAX_CONTENT_LEN. - * - * It is possible to save RAM by setting a smaller outward buffer, while keeping - * the default inward 16384 byte buffer to conform to the TLS specification. - * - * The minimum required outward buffer size is determined by the handshake - * protocol's usage. Handshaking will fail if the outward buffer is too small. - * The specific size requirement depends on the configured ciphers and any - * certificate data which is sent during the handshake. - * - * Uncomment to set the maximum plaintext size of the outgoing I/O buffer - * independently of the incoming I/O buffer. - */ -//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 - -/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING - * - * Maximum number of heap-allocated bytes for the purpose of - * DTLS handshake message reassembly and future message buffering. - * - * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN - * to account for a reassembled handshake message of maximum size, - * together with its reassembly bitmap. - * - * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) - * should be sufficient for all practical situations as it allows - * to reassembly a large handshake message (such as a certificate) - * while buffering multiple smaller handshake messages. - * - */ -//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 - -//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session -// tickets (if enabled) */ #define MBEDTLS_PSK_MAX_LEN 32 /**< Max -// size of TLS pre-shared keys, in bytes (default 256 bits) */ #define -// MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS -// cookies, in seconds if HAVE_TIME, or in number of cookies issued */ - -/** \def MBEDTLS_TLS_EXT_CID - * - * At the time of writing, the CID extension has not been assigned its - * final value. Set this configuration option to make Mbed TLS use a - * different value. - * - * A future minor revision of Mbed TLS may change the default value of - * this option to match evolving standards and usage. - */ -//#define MBEDTLS_TLS_EXT_CID 254 - -/** - * Complete list of ciphersuites to use, in order of preference. - * - * \warning No dependency checking is done on that field! This option can only - * be used to restrict the set of available ciphersuites. It is your - * responsibility to make sure the needed modules are active. - * - * Use this to save a few hundred bytes of ROM (default ordering of all - * available ciphersuites) and a few to a few hundred bytes of RAM. - * - * The value below is only an example, not the default. - */ -//#define MBEDTLS_SSL_CIPHERSUITES -// MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - -/* X509 options */ -//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of -// intermediate CAs in a verification chain. */ #define -// MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename -// string in bytes including the null terminator character ('\0'). */ - -/** - * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake - * signature and ciphersuite selection. Without this build-time option, SHA-1 - * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. - * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by - * default. At the time of writing, there is no practical attack on the use - * of SHA-1 in handshake signatures, hence this option is turned on by default - * to preserve compatibility with existing peers, but the general - * warning applies nonetheless: - * - * \warning SHA-1 is considered a weak message digest and its use constitutes - * a security risk. If possible, we recommend avoiding dependencies - * on it, and considering stronger message digests instead. - * - */ -//#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE - -/** - * Uncomment the macro to let mbed TLS use your alternate implementation of - * mbedtls_platform_zeroize(). This replaces the default implementation in - * platform_util.c. - * - * mbedtls_platform_zeroize() is a widely used function across the library to - * zero a block of memory. The implementation is expected to be secure in the - * sense that it has been written to prevent the compiler from removing calls - * to mbedtls_platform_zeroize() as part of redundant code elimination - * optimizations. However, it is difficult to guarantee that calls to - * mbedtls_platform_zeroize() will not be optimized by the compiler as older - * versions of the C language standards do not provide a secure implementation - * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to - * configure their own implementation of mbedtls_platform_zeroize(), for - * example by using directives specific to their compiler, features from newer - * C standards (e.g using memset_s() in C11) or calling a secure memset() from - * their system (e.g explicit_bzero() in BSD). - */ -//#define MBEDTLS_PLATFORM_ZEROIZE_ALT - -/** - * Uncomment the macro to let Mbed TLS use your alternate implementation of - * mbedtls_platform_gmtime_r(). This replaces the default implementation in - * platform_util.c. - * - * gmtime() is not a thread-safe function as defined in the C standard. The - * library will try to use safer implementations of this function, such as - * gmtime_r() when available. However, if Mbed TLS cannot identify the target - * system, the implementation of mbedtls_platform_gmtime_r() will default to - * using the standard gmtime(). In this case, calls from the library to - * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex - * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the - * library are also guarded with this mutex to avoid race conditions. However, - * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will - * unconditionally use the implementation for mbedtls_platform_gmtime_r() - * supplied at compile time. - */ -//#define MBEDTLS_PLATFORM_GMTIME_R_ALT - -/** - * Enable the verified implementations of ECDH primitives from Project Everest - * (currently only Curve25519). This feature changes the layout of ECDH - * contexts and therefore is a compatibility break for applications that access - * fields of a mbedtls_ecdh_context structure directly. See also - * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. - */ -//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED - -/** \} name SECTION: Module configuration options */ - -/* Target and application specific configurations - * - * Allow user to override any previous default. - * - */ -#if defined(MBEDTLS_USER_CONFIG_FILE) -#include MBEDTLS_USER_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) -#include "mbedtls/config_psa.h" -#endif - -#include "mbedtls/check_config.h" - -#endif /* MBEDTLS_CONFIG_H */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h b/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h deleted file mode 100644 index f1bbd98c8b..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h +++ /dev/null @@ -1,927 +0,0 @@ -/** - * \file oid.h - * - * \brief Object Identifier (OID) database - */ -/* - * 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. - */ -#ifndef MBEDTLS_OID_H -#define MBEDTLS_OID_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/asn1.h" -#include "mbedtls/pk.h" - -#include - -#if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "mbedtls/md.h" -#endif - -/** OID is not found. */ -#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E -/** output buffer is too small */ -#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B - -/* This is for the benefit of X.509, but defined here in order to avoid - * having a "backwards" include of x.509.h here */ -/* - * X.509 extension types (internal, arbitrary values for bitsets) - */ -#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) -#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) -#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) -#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) -#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) -#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) -#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) -#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) -#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) -#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) -#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) -#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) -#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) -#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) -#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) -#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) - -/* - * Top level OID tuples - */ -#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ -#define MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - "\x2b" /* {iso(1) identified-organization(3)} */ -#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ -#define MBEDTLS_OID_ISO_ITU_COUNTRY \ - "\x60" /* {joint-iso-itu-t(2) country(16)} */ - -/* - * ISO Member bodies OID parts - */ -#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ -#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY \ - "\x86\xf7\x0d" /* {rsadsi(113549)} \ - */ -#define MBEDTLS_OID_RSA_COMPANY \ - MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) \ - rsadsi(113549)} */ -#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ -#define MBEDTLS_OID_ANSI_X9_62 \ - MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_ANSI_X9_62 - -/* - * ISO Identified organization OID parts - */ -#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ -#define MBEDTLS_OID_ORG_OIW "\x0e" -#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" -#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" -#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" -#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ -#define MBEDTLS_OID_CERTICOM \ - MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM -#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ -#define MBEDTLS_OID_TELETRUST \ - MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST - -/* - * ISO ITU OID parts - */ -#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ -#define MBEDTLS_OID_ISO_ITU_US_ORG \ - MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) \ - organization(1)} */ - -#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ -#define MBEDTLS_OID_GOV \ - MBEDTLS_OID_ISO_ITU_US_ORG \ - MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) \ - organization(1) gov(101)} */ - -#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ -#define MBEDTLS_OID_NETSCAPE \ - MBEDTLS_OID_ISO_ITU_US_ORG \ - MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) \ - us(840) organization(1) netscape(113730)} */ - -/* ISO arc for standard certificate and CRL extensions */ -#define MBEDTLS_OID_ID_CE \ - MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= \ - {joint-iso-ccitt(2) ds(5) 29} */ - -#define MBEDTLS_OID_NIST_ALG \ - MBEDTLS_OID_GOV \ - "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) \ - gov(101) csor(3) nistAlgorithm(4) */ - -/** - * Private Internet Extensions - * { iso(1) identified-organization(3) dod(6) internet(1) - * security(5) mechanisms(5) pkix(7) } - */ -#define MBEDTLS_OID_INTERNET \ - MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" -#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" - -/* - * Arc for standard naming attributes - */ -#define MBEDTLS_OID_AT \ - MBEDTLS_OID_ISO_CCITT_DS \ - "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ -#define MBEDTLS_OID_AT_CN \ - MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ -#define MBEDTLS_OID_AT_SUR_NAME \ - MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ -#define MBEDTLS_OID_AT_SERIAL_NUMBER \ - MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ -#define MBEDTLS_OID_AT_COUNTRY \ - MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ -#define MBEDTLS_OID_AT_LOCALITY \ - MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ -#define MBEDTLS_OID_AT_STATE \ - MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ -#define MBEDTLS_OID_AT_ORGANIZATION \ - MBEDTLS_OID_AT \ - "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ -#define MBEDTLS_OID_AT_ORG_UNIT \ - MBEDTLS_OID_AT \ - "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ -#define MBEDTLS_OID_AT_TITLE \ - MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ -#define MBEDTLS_OID_AT_POSTAL_ADDRESS \ - MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ -#define MBEDTLS_OID_AT_POSTAL_CODE \ - MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ -#define MBEDTLS_OID_AT_GIVEN_NAME \ - MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ -#define MBEDTLS_OID_AT_INITIALS \ - MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ -#define MBEDTLS_OID_AT_GENERATION_QUALIFIER \ - MBEDTLS_OID_AT \ - "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ -#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER \ - MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} \ - */ -#define MBEDTLS_OID_AT_DN_QUALIFIER \ - MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ -#define MBEDTLS_OID_AT_PSEUDONYM \ - MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ - -#define MBEDTLS_OID_DOMAIN_COMPONENT \ - "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent \ - AttributeType:= {itu-t(0) \ - data(9) pss(2342) \ - ucl(19200300) pilot(100) \ - pilotAttributeType(1) \ - domainComponent(25)} */ - -/* - * OIDs for standard certificate extensions - */ -#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER \ - MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER \ - ::= { id-ce 35 } */ -#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER \ - MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER \ - ::= { id-ce 14 } */ -#define MBEDTLS_OID_KEY_USAGE \ - MBEDTLS_OID_ID_CE \ - "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ -#define MBEDTLS_OID_CERTIFICATE_POLICIES \ - MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER \ - ::= { id-ce 32 } */ -#define MBEDTLS_OID_POLICY_MAPPINGS \ - MBEDTLS_OID_ID_CE \ - "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ -#define MBEDTLS_OID_SUBJECT_ALT_NAME \ - MBEDTLS_OID_ID_CE \ - "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ -#define MBEDTLS_OID_ISSUER_ALT_NAME \ - MBEDTLS_OID_ID_CE \ - "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ -#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS \ - MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT \ - IDENTIFIER ::= { id-ce 9 } */ -#define MBEDTLS_OID_BASIC_CONSTRAINTS \ - MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= \ - { id-ce 19 } */ -#define MBEDTLS_OID_NAME_CONSTRAINTS \ - MBEDTLS_OID_ID_CE \ - "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ -#define MBEDTLS_OID_POLICY_CONSTRAINTS \ - MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= \ - { id-ce 36 } */ -#define MBEDTLS_OID_EXTENDED_KEY_USAGE \ - MBEDTLS_OID_ID_CE \ - "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ -#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS \ - MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER \ - ::= { id-ce 31 } */ -#define MBEDTLS_OID_INIHIBIT_ANYPOLICY \ - MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= \ - { id-ce 54 } */ -#define MBEDTLS_OID_FRESHEST_CRL \ - MBEDTLS_OID_ID_CE \ - "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - -/* - * Certificate policies - */ -#define MBEDTLS_OID_ANY_POLICY \ - MBEDTLS_OID_CERTIFICATE_POLICIES \ - "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies \ - 0 } */ - -/* - * Netscape certificate extensions - */ -#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" -#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" -#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" -#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" -#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" -#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" -#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" -#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" -#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" -#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" -#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" - -/* - * OIDs for CRL extensions - */ -#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" -#define MBEDTLS_OID_CRL_NUMBER \ - MBEDTLS_OID_ID_CE \ - "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - -/* - * X.509 v3 Extended key usage OIDs - */ -#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE \ - MBEDTLS_OID_EXTENDED_KEY_USAGE \ - "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { \ - id-ce-extKeyUsage 0 } */ - -#define MBEDTLS_OID_KP \ - MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ -#define MBEDTLS_OID_SERVER_AUTH \ - MBEDTLS_OID_KP \ - "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ -#define MBEDTLS_OID_CLIENT_AUTH \ - MBEDTLS_OID_KP \ - "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ -#define MBEDTLS_OID_CODE_SIGNING \ - MBEDTLS_OID_KP \ - "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ -#define MBEDTLS_OID_EMAIL_PROTECTION \ - MBEDTLS_OID_KP \ - "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ -#define MBEDTLS_OID_TIME_STAMPING \ - MBEDTLS_OID_KP \ - "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ -#define MBEDTLS_OID_OCSP_SIGNING \ - MBEDTLS_OID_KP \ - "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - -/** - * Wi-SUN Alliance Field Area Network - * { iso(1) identified-organization(3) dod(6) internet(1) - * private(4) enterprise(1) WiSUN(45605) - * FieldAreaNetwork(1) } - */ -#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" - -#define MBEDTLS_OID_ON \ - MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ -#define MBEDTLS_OID_ON_HW_MODULE_NAME \ - MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { \ - id-on 4 } */ - -/* - * PKCS definition OIDs - */ - -#define MBEDTLS_OID_PKCS \ - MBEDTLS_OID_RSA_COMPANY \ - "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) \ - rsadsi(113549) 1 } */ -#define MBEDTLS_OID_PKCS1 \ - MBEDTLS_OID_PKCS \ - "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) \ - rsadsi(113549) pkcs(1) 1 } */ -#define MBEDTLS_OID_PKCS5 \ - MBEDTLS_OID_PKCS \ - "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) \ - rsadsi(113549) pkcs(1) 5 } */ -#define MBEDTLS_OID_PKCS9 \ - MBEDTLS_OID_PKCS \ - "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) \ - rsadsi(113549) pkcs(1) 9 } */ -#define MBEDTLS_OID_PKCS12 \ - MBEDTLS_OID_PKCS \ - "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) \ - us(840) rsadsi(113549) pkcs(1) 12 } */ - -/* - * PKCS#1 OIDs - */ -#define MBEDTLS_OID_PKCS1_RSA \ - MBEDTLS_OID_PKCS1 \ - "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ -#define MBEDTLS_OID_PKCS1_MD2 \ - MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ -#define MBEDTLS_OID_PKCS1_MD4 \ - MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ -#define MBEDTLS_OID_PKCS1_MD5 \ - MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ -#define MBEDTLS_OID_PKCS1_SHA1 \ - MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ -#define MBEDTLS_OID_PKCS1_SHA224 \ - MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ -#define MBEDTLS_OID_PKCS1_SHA256 \ - MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ -#define MBEDTLS_OID_PKCS1_SHA384 \ - MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ -#define MBEDTLS_OID_PKCS1_SHA512 \ - MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ - -#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - -#define MBEDTLS_OID_PKCS9_EMAIL \ - MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ - -/* RFC 4055 */ -#define MBEDTLS_OID_RSASSA_PSS \ - MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ -#define MBEDTLS_OID_MGF1 \ - MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ - -/* - * Digest algorithms - */ -#define MBEDTLS_OID_DIGEST_ALG_MD2 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 \ - } */ -#define MBEDTLS_OID_DIGEST_ALG_MD4 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 \ - } */ -#define MBEDTLS_OID_DIGEST_ALG_MD5 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 \ - } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA1 \ - MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { \ - iso(1) identified-organization(3) oiw(14) \ - secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 \ - MBEDTLS_OID_NIST_ALG \ - "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) \ - country(16) us(840) organization(1) gov(101) csor(3) \ - nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 \ - MBEDTLS_OID_NIST_ALG \ - "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { \ - joint-iso-itu-t(2) country(16) us(840) organization(1) \ - gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA384 \ - MBEDTLS_OID_NIST_ALG \ - "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) \ - country(16) us(840) organization(1) gov(101) csor(3) \ - nistalgorithm(4) hashalgs(2) 2 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA512 \ - MBEDTLS_OID_NIST_ALG \ - "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { \ - joint-iso-itu-t(2) country(16) us(840) organization(1) \ - gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ - -#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 \ - MBEDTLS_OID_TELETRUST \ - "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) \ - identified-organization(3) teletrust(36) algorithm(3) \ - hashAlgorithm(2) ripemd160(1) } */ - -#define MBEDTLS_OID_HMAC_SHA1 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 \ - } */ - -#define MBEDTLS_OID_HMAC_SHA224 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 \ - } */ - -#define MBEDTLS_OID_HMAC_SHA256 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 \ - } */ - -#define MBEDTLS_OID_HMAC_SHA384 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) \ - 10 } */ - -#define MBEDTLS_OID_HMAC_SHA512 \ - MBEDTLS_OID_RSA_COMPANY \ - "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) \ - 11 } */ - -/* - * Encryption algorithms - */ -#define MBEDTLS_OID_DES_CBC \ - MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG \ - "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) \ - identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } \ - */ -#define MBEDTLS_OID_DES_EDE3_CBC \ - MBEDTLS_OID_RSA_COMPANY \ - "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) \ - member-body(2) -- us(840) rsadsi(113549) \ - encryptionAlgorithm(3) 7 } */ -#define MBEDTLS_OID_AES \ - MBEDTLS_OID_NIST_ALG \ - "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) \ - us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } \ - */ - -/* - * Key Wrapping algorithms - */ -/* - * RFC 5649 - */ -#define MBEDTLS_OID_AES128_KW \ - MBEDTLS_OID_AES \ - "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ -#define MBEDTLS_OID_AES128_KWP \ - MBEDTLS_OID_AES \ - "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ -#define MBEDTLS_OID_AES192_KW \ - MBEDTLS_OID_AES \ - "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ -#define MBEDTLS_OID_AES192_KWP \ - MBEDTLS_OID_AES \ - "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ -#define MBEDTLS_OID_AES256_KW \ - MBEDTLS_OID_AES \ - "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ -#define MBEDTLS_OID_AES256_KWP \ - MBEDTLS_OID_AES \ - "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ -/* - * PKCS#5 OIDs - */ -#define MBEDTLS_OID_PKCS5_PBKDF2 \ - MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ -#define MBEDTLS_OID_PKCS5_PBES2 \ - MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ -#define MBEDTLS_OID_PKCS5_PBMAC1 \ - MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ - -/* - * PKCS#5 PBES1 algorithms - */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC \ - MBEDTLS_OID_PKCS5 \ - "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ - -/* - * PKCS#8 OIDs - */ -#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ \ - MBEDTLS_OID_PKCS9 \ - "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ - -/* - * PKCS#12 PBE OIDs - */ -#define MBEDTLS_OID_PKCS12_PBE \ - MBEDTLS_OID_PKCS12 \ - "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ - -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 \ - MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER \ - ::= {pkcs-12PbeIds 1} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 \ - MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER \ - ::= {pkcs-12PbeIds 2} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC \ - MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT \ - IDENTIFIER ::= {pkcs-12PbeIds 3} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC \ - MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT \ - IDENTIFIER ::= {pkcs-12PbeIds 4} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC \ - MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT \ - IDENTIFIER ::= {pkcs-12PbeIds 5} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC \ - MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT \ - IDENTIFIER ::= {pkcs-12PbeIds 6} */ - -/* - * EC key algorithms from RFC 5480 - */ - -/* id-ecPublicKey OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ -#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" - -/* id-ecDH OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) - * schemes(1) ecdh(12) } */ -#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" - -/* - * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 - */ - -/* secp192r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ -#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" - -/* secp224r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ -#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" - -/* secp256r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ -#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" - -/* secp384r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ -#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" - -/* secp521r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ -#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" - -/* secp192k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ -#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" - -/* secp224k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ -#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" - -/* secp256k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ -#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" - -/* RFC 5639 4.1 - * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) - * identified-organization(3) teletrust(36) algorithm(3) signature- - * algorithm(3) ecSign(2) 8} - * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} - * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ -#define MBEDTLS_OID_EC_BRAINPOOL_V1 \ - MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" - -/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ -#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" - -/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ -#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" - -/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ -#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" - -/* - * SEC1 C.1 - * - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} - */ -#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" -#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD \ - MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" - -/* - * ECDSA signature identifiers, from RFC 5480 - */ -#define MBEDTLS_OID_ANSI_X9_62_SIG \ - MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ -#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 \ - MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ - -/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" - -/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" - -/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 2 } */ -#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" - -/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 3 } */ -#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" - -/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 4 } */ -#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Base OID descriptor structure - */ -typedef struct mbedtls_oid_descriptor_t { - const char *asn1; /*!< OID ASN.1 representation */ - size_t asn1_len; /*!< length of asn1 */ - const char *name; /*!< official name (e.g. from RFC) */ - const char *description; /*!< human friendly description */ -} mbedtls_oid_descriptor_t; - -/** - * \brief Translate an ASN.1 OID into its numeric representation - * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") - * - * \param buf buffer to put representation in - * \param size size of the buffer - * \param oid OID to translate - * - * \return Length of the string written (excluding final NULL) or - * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error - */ -int mbedtls_oid_get_numeric_string(char *buf, size_t size, - const mbedtls_asn1_buf *oid); - -/** - * \brief Translate an X.509 extension OID into local values - * - * \param oid OID to use - * \param ext_type place to store the extension type - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); - -/** - * \brief Translate an X.509 attribute type OID into the short name - * (e.g. the OID for an X520 Common Name into "CN") - * - * \param oid OID to use - * \param short_name place to store the string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, - const char **short_name); - -/** - * \brief Translate PublicKeyAlgorithm OID into pk_type - * - * \param oid OID to use - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, - mbedtls_pk_type_t *pk_alg); - -/** - * \brief Translate pk_type into PublicKeyAlgorithm OID - * - * \param pk_alg Public key type to look for - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, const char **oid, - size_t *olen); - -#if defined(TINYCRYPT_PRIMITIVES) -typedef enum { - MBEDTLS_UECC_DP_NONE = 0, /*!< Curve not defined. */ - MBEDTLS_UECC_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve - defined by FIPS 186-4 and SEC1. */ -} mbedtls_uecc_group_id; - -int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, - mbedtls_uecc_group_id *grp_id); - -int mbedtls_oid_get_oid_by_ec_grp(mbedtls_uecc_group_id grp_id, - const char **oid, size_t *olen); -#else -#if defined(MBEDTLS_ECP_C) -/** - * \brief Translate NamedCurve OID into an EC group identifier - * - * \param oid OID to use - * \param grp_id place to store group id - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, - mbedtls_ecp_group_id *grp_id); - -/** - * \brief Translate EC group identifier into NamedCurve OID - * - * \param grp_id EC group identifier - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, const char **oid, - size_t *olen); -#endif /* MBEDTLS_ECP_C */ -#endif - -#if defined(MBEDTLS_MD_C) -/** - * \brief Translate SignatureAlgorithm OID into md_type and pk_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, - mbedtls_pk_type_t *pk_alg); - -/** - * \brief Translate SignatureAlgorithm OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, - const char **desc); - -/** - * \brief Translate md_type and pk_type into SignatureAlgorithm OID - * - * \param md_alg message digest algorithm - * \param pk_alg public key algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, - mbedtls_md_type_t md_alg, const char **oid, - size_t *olen); - -/** - * \brief Translate hash algorithm OID into md_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg); - -/** - * \brief Translate hmac algorithm OID into md_type - * - * \param oid OID to use - * \param md_hmac place to store message hmac algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_hmac); -#endif /* MBEDTLS_MD_C */ - -/** - * \brief Translate Extended Key Usage OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, - const char **desc); - -/** - * \brief Translate certificate policies OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, - const char **desc); - -/** - * \brief Translate md_type into hash algorithm OID - * - * \param md_alg message digest algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, - size_t *olen); - -#if defined(MBEDTLS_CIPHER_C) -/** - * \brief Translate encryption algorithm OID into cipher_type - * - * \param oid OID to use - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, - mbedtls_cipher_type_t *cipher_alg); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_PKCS12_C) -/** - * \brief Translate PKCS#12 PBE algorithm OID into md_type and - * cipher_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, - mbedtls_cipher_type_t *cipher_alg); -#endif /* MBEDTLS_PKCS12_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* oid.h */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h b/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h deleted file mode 100644 index 62dfc87ff0..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h +++ /dev/null @@ -1,936 +0,0 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer - */ -/* - * 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. - */ - -#ifndef MBEDTLS_PK_H -#define MBEDTLS_PK_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/md.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "tinycrypt/ecc.h" -#endif - -#if (defined(__ARMCC_VERSION) || defined(_MSC_VER)) && !defined(inline) && \ - !defined(__cplusplus) -#define inline __inline -#endif - -/** Memory allocation failed. */ -#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 -/** Type mismatch, eg attempt to encrypt with an ECDSA key */ -#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 -/** Bad input parameters to function. */ -#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 -/** Read/write of file failed. */ -#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 -/** Unsupported key version */ -#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 -/** Invalid key tag or value. */ -#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 -/** Key algorithm is unsupported (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 -/** Private key password can't be empty. */ -#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 -/** Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 -/** The pubkey tag or value is invalid (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 -/** The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 -/** Elliptic curve is unsupported (only NIST curves are supported). */ -#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 -/** Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 -/** The buffer contains a valid signature followed by more data. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 - -/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ -/** PK hardware accelerator failed. */ -#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Public key types - */ -typedef enum { - MBEDTLS_PK_NONE = 0, - MBEDTLS_PK_RSA, - MBEDTLS_PK_ECKEY, - MBEDTLS_PK_ECKEY_DH, - MBEDTLS_PK_ECDSA, - MBEDTLS_PK_RSA_ALT, - MBEDTLS_PK_RSASSA_PSS, - MBEDTLS_PK_OPAQUE, -} mbedtls_pk_type_t; - -/** - * \brief Options for RSASSA-PSS signature verification. - * See \c mbedtls_rsa_rsassa_pss_verify_ext() - */ -typedef struct mbedtls_pk_rsassa_pss_options { - mbedtls_md_type_t mgf1_hash_id; - int expected_salt_len; - -} mbedtls_pk_rsassa_pss_options; - -/** - * \brief Maximum size of a signature made by mbedtls_pk_sign(). - */ -/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature - * size among the supported signature types. Do it by starting at 0, - * then incrementally increasing to be large enough for each supported - * signature mechanism. - * - * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled - * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C - * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). - */ -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 - -#if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \ - MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* For RSA, the signature can be as large as the bignum module allows. - * For RSA_ALT, the signature size is not necessarily tied to what the - * bignum module can do, but in the absence of any specific setting, - * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE -#endif - -#if defined(MBEDTLS_ECDSA_C) && \ - MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* For ECDSA, the ecdsa module exports a constant for the maximum - * signature size. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made - * through the PSA API in the PSA representation. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE -#endif - -#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* The Mbed TLS representation is different for ECDSA signatures: - * PSA uses the raw concatenation of r and s, - * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). - * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the - * types, lengths (represented by up to 2 bytes), and potential leading - * zeros of the INTEGERs and the SEQUENCE. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11) -#endif -#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ - -/** - * \brief Types for interfacing with the debug module - */ -typedef enum { - MBEDTLS_PK_DEBUG_NONE = 0, - MBEDTLS_PK_DEBUG_MPI, - MBEDTLS_PK_DEBUG_ECP, -} mbedtls_pk_debug_type; - -/** - * \brief Item to send to the debug module - */ -typedef struct mbedtls_pk_debug_item { - mbedtls_pk_debug_type type; - const char *name; - void *value; -} mbedtls_pk_debug_item; - -/** Maximum number of item send for debugging, plus 1 */ -#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 - -/** - * \brief Public key information and operations - */ -typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - -#if defined(TINYCRYPT_PRIMITIVES) -typedef struct { - uint8_t private_key[NUM_ECC_BYTES]; - uint8_t public_key[2 * NUM_ECC_BYTES]; -} mbedtls_uecc_keypair; -#endif - -/** - * \brief Public key container - */ -typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t *pk_info; /**< Public key information */ - void *pk_ctx; /**< Underlying public key context */ -} mbedtls_pk_context; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/** - * \brief Context for resuming operations - */ -typedef struct { - const mbedtls_pk_info_t *pk_info; /**< Public key information */ - void *rs_ctx; /**< Underlying restart context */ -} mbedtls_pk_restart_ctx; -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ -/* Now we can declare functions that take a pointer to that */ -typedef void mbedtls_pk_restart_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -#if defined(TINYCRYPT_PRIMITIVES) - -static inline mbedtls_uecc_keypair * -mbedtls_pk_uecc(const mbedtls_pk_context pk) { - return ((mbedtls_uecc_keypair *)(pk).pk_ctx); -} - -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Types for RSA-alt abstraction - */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, int mode, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len); -typedef int (*mbedtls_pk_rsa_alt_sign_func)( - void *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig); -typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Return information associated with the given PK type - * - * \param pk_type PK type to search for. - * - * \return The PK info associated with the type or NULL if not found. - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); - -/** - * \brief Initialize a #mbedtls_pk_context (as NONE). - * - * \param ctx The context to initialize. - * This must not be \c NULL. - */ -void mbedtls_pk_init(mbedtls_pk_context *ctx); - -/** - * \brief Free the components of a #mbedtls_pk_context. - * - * \param ctx The context to clear. It must have been initialized. - * If this is \c NULL, this function does nothing. - * - * \note For contexts that have been set up with - * mbedtls_pk_setup_opaque(), this does not free the underlying - * PSA key and you still need to call psa_destroy_key() - * independently if you want to destroy that key. - */ -void mbedtls_pk_free(mbedtls_pk_context *ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/** - * \brief Initialize a restart context - * - * \param ctx The context to initialize. - * This must not be \c NULL. - */ -void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx); - -/** - * \brief Free the components of a restart context - * - * \param ctx The context to clear. It must have been initialized. - * If this is \c NULL, this function does nothing. - */ -void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/** - * \brief Initialize a PK context with the information given - * and allocates the type-specific PK subcontext. - * - * \param ctx Context to initialize. It must not have been set - * up yet (type #MBEDTLS_PK_NONE). - * \param info Information to use - * - * \return 0 on success, - * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, - * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - * - * \note For contexts holding an RSA-alt key, use - * \c mbedtls_pk_setup_rsa_alt() instead. - */ -int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Initialize a PK context to wrap a PSA key. - * - * \note This function replaces mbedtls_pk_setup() for contexts - * that wrap a (possibly opaque) PSA key instead of - * storing and manipulating the key material directly. - * - * \param ctx The context to initialize. It must be empty (type NONE). - * \param key The PSA key to wrap, which must hold an ECC key pair - * (see notes below). - * - * \note The wrapped key must remain valid as long as the - * wrapping PK context is in use, that is at least between - * the point this function is called and the point - * mbedtls_pk_free() is called on this context. The wrapped - * key might then be independently used or destroyed. - * - * \note This function is currently only available for ECC key - * pairs (that is, ECC keys containing private key material). - * Support for other key types may be added later. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input - * (context already used, invalid key identifier). - * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an - * ECC key pair. - * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - */ -int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const psa_key_id_t key); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Initialize an RSA-alt context - * - * \param ctx Context to initialize. It must not have been set - * up yet (type #MBEDTLS_PK_NONE). - * \param key RSA key pointer - * \param decrypt_func Decryption function - * \param sign_func Signing function - * \param key_len_func Function returning key length in bytes - * - * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the - * context wasn't already initialized as RSA_ALT. - * - * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. - */ -int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Get the size in bits of the underlying key - * - * \param ctx The context to query. It must have been initialized. - * - * \return Key size in bits, or 0 on error - */ -size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); - -/** - * \brief Get the length in bytes of the underlying key - * - * \param ctx The context to query. It must have been initialized. - * - * \return Key length in bytes, or 0 on error - */ -static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) { - return ((mbedtls_pk_get_bitlen(ctx) + 7) / 8); -} - -/** - * \brief Tell if a context can do the operation given by type - * - * \param ctx The context to query. It must have been initialized. - * \param type The desired type. - * - * \return 1 if the context can do operations on the given type. - * \return 0 if the context cannot do the operations on the given - * type. This is always the case for a context that has - * been initialized but not set up, or that has been - * cleared with mbedtls_pk_free(). - */ -int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); - -/** - * \brief Verify signature (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid - * signature in sig but its length is less than \p siglen, - * or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) - * to verify RSASSA_PSS signatures. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - */ -int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - -/** - * \brief Restartable version of \c mbedtls_pk_verify() - * - * \note Performs the same job as \c mbedtls_pk_verify(), but can - * return early and restart according to the limit set with - * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC - * operations. For RSA, same as \c mbedtls_pk_verify(). - * - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * \param rs_ctx Restart context (NULL to disable restart) - * - * \return See \c mbedtls_pk_verify(), or - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). - */ -int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - mbedtls_pk_restart_ctx *rs_ctx); - -/** - * \brief Verify signature, with options. - * (Includes verification of the padding depending on type.) - * - * \param type Signature type (inc. possible padding type) to verify - * \param options Pointer to type-specific options, or NULL - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be - * used for this type of signatures, - * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid - * signature in sig but its length is less than \p siglen, - * or a specific error code. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - * - * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point - * to a mbedtls_pk_rsassa_pss_options structure, - * otherwise it must be NULL. - */ -int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - -/** - * \brief Make signature, including padding if relevant. - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Place to write the signature. - * It must have enough room for the signature. - * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. - * You may use a smaller buffer if it is large enough - * given the key type. - * \param sig_len On successful return, - * the number of bytes written to \p sig. - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 on success, or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * There is no interface in the PK module to make RSASSA-PSS - * signatures yet. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. - * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. - */ -int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/** - * \brief Restartable version of \c mbedtls_pk_sign() - * - * \note Performs the same job as \c mbedtls_pk_sign(), but can - * return early and restart according to the limit set with - * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC - * operations. For RSA, same as \c mbedtls_pk_sign(). - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) - * \param sig Place to write the signature. - * It must have enough room for the signature. - * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. - * You may use a smaller buffer if it is large enough - * given the key type. - * \param sig_len On successful return, - * the number of bytes written to \p sig. - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param rs_ctx Restart context (NULL to disable restart) - * - * \return See \c mbedtls_pk_sign(). - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). - */ -int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, mbedtls_pk_restart_ctx *rs_ctx); - -/** - * \brief Decrypt message (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param input Input to decrypt - * \param ilen Input size - * \param output Decrypted output - * \param olen Decrypted message length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen, - size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -/** - * \brief Encrypt message (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up. - * \param input Message to encrypt - * \param ilen Message size - * \param output Encrypted output - * \param olen Encrypted output length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen, - size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -/** - * \brief Check if a public-private pair of keys matches. - * - * \param pub Context holding a public key. - * \param prv Context holding a private (and public) key. - * - * \return \c 0 on success (keys were checked and match each other). - * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not - * be checked - in that case they may or may not match. - * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. - * \return Another non-zero value if the keys do not match. - */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, - const mbedtls_pk_context *prv); - -/** - * \brief Export debug information - * - * \param ctx The PK context to use. It must have been initialized. - * \param items Place to write debug items - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_debug(const mbedtls_pk_context *ctx, - mbedtls_pk_debug_item *items); - -/** - * \brief Access the type name - * - * \param ctx The PK context to use. It must have been initialized. - * - * \return Type name on success, or "invalid PK" - */ -const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); - -/** - * \brief Get the key type - * - * \param ctx The PK context to use. It must have been initialized. - * - * \return Type on success. - * \return #MBEDTLS_PK_NONE for a context that has not been set up. - */ -mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); - -#if defined(MBEDTLS_RSA_C) -/** - * Quick access to an RSA context inside a PK context. - * - * \warning This function can only be used when the type of the context, as - * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. - * Ensuring that is the caller's responsibility. - * Alternatively, you can check whether this function returns NULL. - * - * \return The internal RSA context held by the PK context, or NULL. - */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { - switch (mbedtls_pk_get_type(&pk)) { - case MBEDTLS_PK_RSA: - return ((mbedtls_rsa_context *)(pk).pk_ctx); - default: - return (NULL); - } -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * Quick access to an EC context inside a PK context. - * - * \warning This function can only be used when the type of the context, as - * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, - * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. - * Ensuring that is the caller's responsibility. - * Alternatively, you can check whether this function returns NULL. - * - * \return The internal EC context held by the PK context, or NULL. - */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) { - switch (mbedtls_pk_get_type(&pk)) { - case MBEDTLS_PK_ECKEY: - case MBEDTLS_PK_ECKEY_DH: - case MBEDTLS_PK_ECDSA: - return ((mbedtls_ecp_keypair *)(pk).pk_ctx); - default: - return (NULL); - } -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** \ingroup pk_module */ -/** - * \brief Parse a private key in PEM or DER format - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param key Input buffer to parse. - * The buffer must contain the input exactly, with no - * extra trailing material. For PEM, the buffer must - * contain a null-terminated string. - * \param keylen Size of \b key in bytes. - * For PEM data, this includes the terminating null byte, - * so \p keylen must be equal to `strlen(key) + 1`. - * \param pwd Optional password for decryption. - * Pass \c NULL if expecting a non-encrypted key. - * Pass a string of \p pwdlen bytes if expecting an encrypted - * key; a non-encrypted key will also be accepted. - * The empty password is not supported. - * \param pwdlen Size of the password in bytes. - * Ignored if \p pwd is \c NULL. - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, const unsigned char *key, - size_t keylen, const unsigned char *pwd, - size_t pwdlen); - -/** \ingroup pk_module */ -/** - * \brief Parse a public key in PEM or DER format - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param key Input buffer to parse. - * The buffer must contain the input exactly, with no - * extra trailing material. For PEM, the buffer must - * contain a null-terminated string. - * \param keylen Size of \b key in bytes. - * For PEM data, this includes the terminating null byte, - * so \p keylen must be equal to `strlen(key) + 1`. - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen); - -#if defined(MBEDTLS_FS_IO) -/** \ingroup pk_module */ -/** - * \brief Load and parse a private key - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param path filename to read the private key from - * \param password Optional password to decrypt the file. - * Pass \c NULL if expecting a non-encrypted key. - * Pass a null-terminated string if expecting an encrypted - * key; a non-encrypted key will also be accepted. - * The empty password is not supported. - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, - const char *password); - -/** \ingroup pk_module */ -/** - * \brief Load and parse a public key - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param path filename to read the public key from - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with - * mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a private key to a PKCS#1 or SEC1 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx PK context which must contain a valid private key. - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, - size_t size); - -/** - * \brief Write a public key to a SubjectPublicKeyInfo DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx PK context which must contain a valid public or private key. - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *ctx, unsigned char *buf, - size_t size); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a public key to a PEM string - * - * \param ctx PK context which must contain a valid public or private key. - * \param buf Buffer to write to. The output includes a - * terminating null byte. - * \param size Size of the buffer in bytes. - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *ctx, unsigned char *buf, - size_t size); - -/** - * \brief Write a private key to a PKCS#1 or SEC1 PEM string - * - * \param ctx PK context which must contain a valid private key. - * \param buf Buffer to write to. The output includes a - * terminating null byte. - * \param size Size of the buffer in bytes. - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_key_pem(mbedtls_pk_context *ctx, unsigned char *buf, - size_t size); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * WARNING: Low-level functions. You probably do not want to use these unless - * you are certain you do ;) - */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** - * \brief Parse a SubjectPublicKeyInfo DER structure - * - * \param p the position in the ASN.1 data - * \param end end of the buffer - * \param pk The PK context to fill. It must have been initialized - * but not set up. - * - * \return 0 if successful, or a specific PK error code - */ -int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk); -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a subjectPublicKey to ASN.1 data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param key PK context which must contain a valid public or private key. - * - * \return the length written or a negative error code - */ -int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key); -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -#if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Turn an EC key into an opaque one. - * - * \warning This is a temporary utility function for tests. It might - * change or be removed at any time without notice. - * - * \note Only ECDSA keys are supported so far. Signing with the - * specified hash is the only allowed use of that key. - * - * \param pk Input: the EC key to import to a PSA key. - * Output: a PK context wrapping that PSA key. - * \param key Output: a PSA key identifier. - * It's the caller's responsibility to call - * psa_destroy_key() on that key identifier after calling - * mbedtls_pk_free() on the PK context. - * \param hash_alg The hash algorithm to allow for use with that key. - * - * \return \c 0 if successful. - * \return An Mbed TLS error code otherwise. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_key_id_t *key, - psa_algorithm_t hash_alg); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PK_H */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/pk_internal.h b/matter/mbedtls/tinycrypt/inc/mbedtls/pk_internal.h deleted file mode 100644 index ecb89b6e8e..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/pk_internal.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * \file pk_internal.h - * - * \brief Public Key abstraction layer: wrapper functions - */ -/* - * 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. - */ - -#ifndef MBEDTLS_PK_WRAP_H -#define MBEDTLS_PK_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/pk.h" - -struct mbedtls_pk_info_t { - /** Public key type */ - mbedtls_pk_type_t type; - - /** Type name */ - const char *name; - - /** Get key size in bits */ - size_t (*get_bitlen)(const void *); - - /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ - int (*can_do)(mbedtls_pk_type_t type); - - /** Verify signature */ - int (*verify_func)(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - - /** Make signature */ - int (*sign_func)(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Verify signature (restartable) */ - int (*verify_rs_func)(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, void *rs_ctx); - - /** Make signature (restartable) */ - int (*sign_rs_func)(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, void *rs_ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - /** Decrypt message */ - int (*decrypt_func)(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - - /** Encrypt message */ - int (*encrypt_func)(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - - /** Check public-private key pair */ - int (*check_pair_func)(const void *pub, const void *prv); - - /** Allocate a new context */ - void *(*ctx_alloc_func)(void); - - /** Free the given context */ - void (*ctx_free_func)(void *ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Allocate the restart context */ - void *(*rs_alloc_func)(void); - - /** Free the restart context */ - void (*rs_free_func)(void *rs_ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - /** Interface with the debug module */ - void (*debug_func)(const void *ctx, mbedtls_pk_debug_item *items); -}; -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Container for RSA-alt */ -typedef struct { - void *key; - mbedtls_pk_rsa_alt_decrypt_func decrypt_func; - mbedtls_pk_rsa_alt_sign_func sign_func; - mbedtls_pk_rsa_alt_key_len_func key_len_func; -} mbedtls_rsa_alt_context; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const mbedtls_pk_info_t mbedtls_rsa_info; -#endif - -#if defined(MBEDTLS_ECP_C) -extern const mbedtls_pk_info_t mbedtls_eckey_info; -extern const mbedtls_pk_info_t mbedtls_eckeydh_info; -#endif - -#if defined(MBEDTLS_ECDSA_C) -extern const mbedtls_pk_info_t mbedtls_ecdsa_info; -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -extern const mbedtls_pk_info_t mbedtls_uecc_eckey_info; -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; -#endif - -#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/platform.h b/matter/mbedtls/tinycrypt/inc/mbedtls/platform.h deleted file mode 100644 index e8801e2046..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/platform.h +++ /dev/null @@ -1,448 +0,0 @@ -/** - * \file platform.h - * - * \brief This file contains the definitions and functions of the - * Mbed TLS platform abstraction layer. - * - * The platform abstraction layer removes the need for the library - * to directly link to standard C library functions or operating - * system services, making the library easier to port and embed. - * Application developers and users of the library can provide their own - * implementations of these functions, or implementations specific to - * their platform, which can be statically linked to the library or - * dynamically configured at runtime. - */ -/* - * 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. - */ -#ifndef MBEDTLS_PLATFORM_H -#define MBEDTLS_PLATFORM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED \ - -0x0070 /**< Hardware accelerator failed */ -#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED \ - -0x0072 /**< The requested feature is not supported by the platform */ -#define MBEDTLS_ERR_PLATFORM_FAULT_DETECTED \ - -0x0071 /**< A hardware fault was detected in a critical path. As a security \ - precaution this should be treated as a potential physical attack \ - */ -#define MBEDTLS_ERR_PLATFORM_ALLOC_FAILED \ - -0x0076 /**< Memory allocation failed */ -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -/** Hardware accelerator failed */ -#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 -/** The requested feature is not supported by the platform */ -#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -/* The older Microsoft Windows common runtime provides non-conforming - * implementations of some standard library functions, including snprintf - * and vsnprintf. This affects MSVC and MinGW builds. - */ -#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) -#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF -#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF -#endif - -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#include -#include -#if defined(MBEDTLS_HAVE_TIME) -#include -#endif -#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) -#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) -#define MBEDTLS_PLATFORM_STD_SNPRINTF \ - mbedtls_platform_win32_snprintf /**< The default \c snprintf function to \ - use. */ -#else -#define MBEDTLS_PLATFORM_STD_SNPRINTF \ - snprintf /**< The default \c snprintf function to use. */ -#endif -#endif -#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) -#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) -#define MBEDTLS_PLATFORM_STD_VSNPRINTF \ - mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to \ - use. */ -#else -#define MBEDTLS_PLATFORM_STD_VSNPRINTF \ - vsnprintf /**< The default \c vsnprintf function to use. */ -#endif -#endif -#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -#define MBEDTLS_PLATFORM_STD_PRINTF \ - printf /**< The default \c printf function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -#define MBEDTLS_PLATFORM_STD_FPRINTF \ - fprintf /**< The default \c fprintf function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -#define MBEDTLS_PLATFORM_STD_CALLOC \ - calloc /**< The default \c calloc function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FREE) -#define MBEDTLS_PLATFORM_STD_FREE \ - free /**< The default \c free function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT) -#define MBEDTLS_PLATFORM_STD_EXIT \ - exit /**< The default \c exit function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_TIME) -#define MBEDTLS_PLATFORM_STD_TIME \ - time /**< The default \c time function to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS \ - EXIT_SUCCESS /**< The default exit value to use. */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE \ - EXIT_FAILURE /**< The default exit value to use. */ -#endif -#if defined(MBEDTLS_FS_IO) -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) -#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" -#endif -#endif /* MBEDTLS_FS_IO */ -#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) -#include MBEDTLS_PLATFORM_STD_MEM_HDR -#endif -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ - -/** \} name SECTION: Module settings */ - -/* - * The function pointers for calloc and free. - */ -#if defined(MBEDTLS_PLATFORM_MEMORY) -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ - defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO -#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO -#else -/* For size_t */ -#include -extern void *mbedtls_calloc(size_t n, size_t size); -extern void mbedtls_free(void *ptr); - -/** - * \brief This function dynamically sets the memory-management - * functions used by the library, during runtime. - * - * \param calloc_func The \c calloc function implementation. - * \param free_func The \c free function implementation. - * - * \return \c 0. - */ -int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), - void (*free_func)(void *)); -#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ -#else /* !MBEDTLS_PLATFORM_MEMORY */ -#define mbedtls_free free -#define mbedtls_calloc calloc -#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ - -/* - * The function pointers for fprintf - */ -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -/* We need FILE * */ -#include -extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...); - -/** - * \brief This function dynamically configures the fprintf - * function that is called when the - * mbedtls_fprintf() function is invoked by the library. - * - * \param fprintf_func The \c fprintf function implementation. - * - * \return \c 0. - */ -int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *, - ...)); -#else -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) -#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO -#else -#define mbedtls_fprintf fprintf -#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ - -/* - * The function pointers for printf - */ -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -extern int (*mbedtls_printf)(const char *format, ...); - -/** - * \brief This function dynamically configures the snprintf - * function that is called when the mbedtls_snprintf() - * function is invoked by the library. - * - * \param printf_func The \c printf function implementation. - * - * \return \c 0 on success. - */ -int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)); -#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) -#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO -#else -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ - -/* - * The function pointers for snprintf - * - * The snprintf implementation should conform to C99: - * - it *must* always correctly zero-terminate the buffer - * (except when n == 0, then it must leave the buffer untouched) - * - however it is acceptable to return -1 instead of the required length when - * the destination buffer is too short. - */ -#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) -/* For Windows (inc. MSYS2), we provide our own fixed implementation */ -int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...); -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...); - -/** - * \brief This function allows configuring a custom - * \c snprintf function pointer. - * - * \param snprintf_func The \c snprintf function implementation. - * - * \return \c 0 on success. - */ -int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, - const char *format, - ...)); -#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO -#else -#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF -#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ - -/* - * The function pointers for vsnprintf - * - * The vsnprintf implementation should conform to C99: - * - it *must* always correctly zero-terminate the buffer - * (except when n == 0, then it must leave the buffer untouched) - * - however it is acceptable to return -1 instead of the required length when - * the destination buffer is too short. - */ -#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) -#include -/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ -int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, - va_list arg); -#endif - -#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) -#include -extern int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, - va_list arg); - -/** - * \brief Set your own snprintf function pointer - * - * \param vsnprintf_func The \c vsnprintf function implementation - * - * \return \c 0 - */ -int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, - const char *format, - va_list arg)); -#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) -#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO -#else -#define mbedtls_vsnprintf vsnprintf -#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ - -/* - * The function pointers for exit - */ -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) -extern void (*mbedtls_exit)(int status); - -/** - * \brief This function dynamically configures the exit - * function that is called when the mbedtls_exit() - * function is invoked by the library. - * - * \param exit_func The \c exit function implementation. - * - * \return \c 0 on success. - */ -int mbedtls_platform_set_exit(void (*exit_func)(int status)); -#else -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) -#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO -#else -#define mbedtls_exit exit -#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ - -/* - * The default exit values - */ -#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS -#else -#define MBEDTLS_EXIT_SUCCESS 0 -#endif -#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE -#else -#define MBEDTLS_EXIT_FAILURE 1 -#endif - -/* - * The function pointers for reading from and writing a seed file to - * Non-Volatile storage (NV) in a platform-independent way - * - * Only enabled when the NV seed entropy source is enabled - */ -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Internal standard platform definitions */ -int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len); -int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len); -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -extern int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len); -extern int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len); - -/** - * \brief This function allows configuring custom seed file writing and - * reading functions. - * - * \param nv_seed_read_func The seed reading function implementation. - * \param nv_seed_write_func The seed writing function implementation. - * - * \return \c 0 on success. - */ -int mbedtls_platform_set_nv_seed(int (*nv_seed_read_func)(unsigned char *buf, - size_t buf_len), - int (*nv_seed_write_func)(unsigned char *buf, - size_t buf_len)); -#else -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ - defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) -#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO -#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO -#else -#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read -#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write -#endif -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) - -/** - * \brief The platform context structure. - * - * \note This structure may be used to assist platform-specific - * setup or teardown operations. - */ -typedef struct mbedtls_platform_context { - char dummy; /**< A placeholder member, as empty structs are not portable. */ -} mbedtls_platform_context; - -#else -#include "platform_alt.h" -#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ - -/** - * \brief This function performs any platform-specific initialization - * operations. - * - * \note This function should be called before any other library functions. - * - * Its implementation is platform-specific, and unless - * platform-specific code is provided, it does nothing. - * - * \note The usage and necessity of this function is dependent on the - * platform. - * - * \param ctx The platform context. - * - * \return \c 0 on success. - */ -int mbedtls_platform_setup(mbedtls_platform_context *ctx); -/** - * \brief This function performs any platform teardown operations. - * - * \note This function should be called after every other Mbed TLS module - * has been correctly freed using the appropriate free function. - * - * Its implementation is platform-specific, and unless - * platform-specific code is provided, it does nothing. - * - * \note The usage and necessity of this function is dependent on the - * platform. - * - * \param ctx The platform context. - * - */ -void mbedtls_platform_teardown(mbedtls_platform_context *ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* platform.h */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/platform_util.h b/matter/mbedtls/tinycrypt/inc/mbedtls/platform_util.h deleted file mode 100644 index 4956047eb8..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/platform_util.h +++ /dev/null @@ -1,462 +0,0 @@ -/** - * \file platform_util.h - * - * \brief Common and shared functions used by multiple modules in the Mbed TLS - * library. - */ -/* - * 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. - */ -#ifndef MBEDTLS_PLATFORM_UTIL_H -#define MBEDTLS_PLATFORM_UTIL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include -#if defined(MBEDTLS_HAVE_TIME_DATE) -#include "mbedtls/platform_time.h" -#include -#endif /* MBEDTLS_HAVE_TIME_DATE */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_CHECK_PARAMS) - -#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) -/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert - * (which is what our config.h suggests). */ -#include -#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ - -#if defined(MBEDTLS_PARAM_FAILED) -/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. - * - * This flag can be used to check whether it is safe to assume that - * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). - */ -#define MBEDTLS_PARAM_FAILED_ALT - -#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) -#define MBEDTLS_PARAM_FAILED(cond) assert(cond) -#define MBEDTLS_PARAM_FAILED_ALT - -#else /* MBEDTLS_PARAM_FAILED */ -#define MBEDTLS_PARAM_FAILED(cond) \ - mbedtls_param_failed(#cond, __FILE__, __LINE__) - -/** - * \brief User supplied callback function for parameter validation - * failure. See #MBEDTLS_CHECK_PARAMS for context. - * - * This function will be called unless an alternative treatment - * is defined through the #MBEDTLS_PARAM_FAILED macro. - * - * This function can return, and the operation will be aborted, or - * alternatively, through use of setjmp()/longjmp() can resume - * execution in the application code. - * - * \param failure_condition The assertion that didn't hold. - * \param file The file where the assertion failed. - * \param line The line in the file where the assertion failed. - */ -void mbedtls_param_failed(const char *failure_condition, const char *file, - int line); -#endif /* MBEDTLS_PARAM_FAILED */ - -/* Internal macro meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE_RET(cond, ret) \ - do { \ - if (!(cond)) { \ - MBEDTLS_PARAM_FAILED(cond); \ - return (ret); \ - } \ - } while (0) - -/* Internal macro meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE(cond) \ - do { \ - if (!(cond)) { \ - MBEDTLS_PARAM_FAILED(cond); \ - return; \ - } \ - } while (0) - -#else /* MBEDTLS_CHECK_PARAMS */ - -/* Internal macros meant to be called only from within the library. */ -#define MBEDTLS_INTERNAL_VALIDATE_RET(cond, ret) \ - do { \ - } while (0) -#define MBEDTLS_INTERNAL_VALIDATE(cond) \ - do { \ - } while (0) - -#endif /* MBEDTLS_CHECK_PARAMS */ - -/* Internal helper macros for deprecating API constants. */ -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here - * to avoid conflict with other headers which define and use - * it, too. We might want to move all these definitions here at - * some point for uniformity. */ -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -MBEDTLS_DEPRECATED typedef char const *mbedtls_deprecated_string_constant_t; -#define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) \ - ((mbedtls_deprecated_string_constant_t)(VAL)) -MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; -#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) \ - ((mbedtls_deprecated_numeric_constant_t)(VAL)) -#undef MBEDTLS_DEPRECATED -#else /* MBEDTLS_DEPRECATED_WARNING */ -#define MBEDTLS_DEPRECATED_STRING_CONSTANT(VAL) VAL -#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(VAL) VAL -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -/* Implementation of the check-return facility. - * See the user documentation in config.h. - * - * Do not use this macro directly to annotate function: instead, - * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL - * depending on how important it is to check the return value. - */ -#if !defined(MBEDTLS_CHECK_RETURN) -#if defined(__GNUC__) -#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) -#elif defined(_MSC_VER) && _MSC_VER >= 1700 -#include -#define MBEDTLS_CHECK_RETURN _Check_return_ -#else -#define MBEDTLS_CHECK_RETURN -#endif -#endif - -/** Critical-failure function - * - * This macro appearing at the beginning of the declaration of a function - * indicates that its return value should be checked in all applications. - * Omitting the check is very likely to indicate a bug in the application - * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN - * is implemented for the compiler in use. - * - * \note The use of this macro is a work in progress. - * This macro may be added to more functions in the future. - * Such an extension is not considered an API break, provided that - * there are near-unavoidable circumstances under which the function - * can fail. For example, signature/MAC/AEAD verification functions, - * and functions that require a random generator, are considered - * return-check-critical. - */ -#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN - -/** Ordinary-failure function - * - * This macro appearing at the beginning of the declaration of a function - * indicates that its return value should be generally be checked in portable - * applications. Omitting the check will result in a compile-time warning if - * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and - * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. - * - * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value - * of a function that is annotated with #MBEDTLS_CHECK_RETURN. - * - * \note The use of this macro is a work in progress. - * This macro will be added to more functions in the future. - * Eventually this should appear before most functions returning - * an error code (as \c int in the \c mbedtls_xxx API or - * as ::psa_status_t in the \c psa_xxx API). - */ -#if defined(MBEDTLS_CHECK_RETURN_WARNING) -#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN -#else -#define MBEDTLS_CHECK_RETURN_TYPICAL -#endif - -/** Benign-failure function - * - * This macro appearing at the beginning of the declaration of a function - * indicates that it is rarely useful to check its return value. - * - * This macro has an empty expansion. It exists for documentation purposes: - * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function - * has been analyzed for return-check usefuless, whereas the lack of - * an annotation indicates that the function has not been analyzed and its - * return-check usefulness is unknown. - */ -#define MBEDTLS_CHECK_RETURN_OPTIONAL - -/** \def MBEDTLS_IGNORE_RETURN - * - * Call this macro with one argument, a function call, to suppress a warning - * from #MBEDTLS_CHECK_RETURN due to that function call. - */ -#if !defined(MBEDTLS_IGNORE_RETURN) -/* GCC doesn't silence the warning with just (void)(result). - * (void)!(result) is known to work up at least up to GCC 10, as well - * as with Clang and MSVC. - * - * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html - * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result - * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 - */ -#define MBEDTLS_IGNORE_RETURN(result) ((void)!(result)) -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -/** - * \brief Securely zeroize a buffer - * - * The function is meant to wipe the data contained in a buffer so - * that it can no longer be recovered even if the program memory - * is later compromised. Call this function on sensitive data - * stored on the stack before returning from a function, and on - * sensitive data stored on the heap before freeing the heap - * object. - * - * It is extremely difficult to guarantee that calls to - * mbedtls_platform_zeroize() are not removed by aggressive - * compiler optimizations in a portable way. For this reason, Mbed - * TLS provides the configuration option - * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure - * mbedtls_platform_zeroize() to use a suitable implementation for - * their platform and needs - * - * \param buf Buffer to be zeroized - * \param len Length of the buffer in bytes - * - * \return The value of \p buf if the operation was successful. - * \return NULL if a potential FI attack was detected or input parameters - * are not valid. - */ -void *mbedtls_platform_zeroize(void *buf, size_t len); - -/** - * \brief Secure memset - * - * This is a constant-time version of memset(). The buffer is - * initialised with random data and the order is also randomised - * using the RNG in order to further harden against side-channel - * attacks. - * - * \param ptr Buffer to be set. - * \param value Value to be used when setting the buffer. - * \param num The length of the buffer in bytes. - * - * \return The value of \p ptr if the operation was successful. - * \return NULL if a potential FI attack was detected. - */ -void *mbedtls_platform_memset(void *ptr, int value, size_t num); - -/** - * \brief Secure memcpy - * - * This is a constant-time version of memcpy(). The buffer is - * initialised with random data and the order is also randomised - * using the RNG in order to further harden against side-channel - * attacks. - * - * \param dst Destination buffer where the data is being copied to. - * \param src Source buffer where the data is being copied from. - * \param num The length of the buffers in bytes. - * - * \return The value of \p dst. - * \return NULL if a potential FI attack was detected. - */ -void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); - -/** - * \brief Secure memmove - * - * This is a constant-time version of memmove(). It is based on - * the double use of the mbedtls_platform_memcpy() function secured - * against side-channel attacks. - * - * \param dst Destination buffer where the data is being moved to. - * \param src Source buffer where the data is being moved from. - * \param num The length of the buffers in bytes. - * - * \return 0 if the operation was successful - * \return #MBEDTLS_ERR_PLATFORM_ALLOC_FAILED if a memory allocation failed - */ -int mbedtls_platform_memmove(void *dst, const void *src, size_t num); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif - -/** - * \brief Secure memcmp - * - * This is a constant-time version of memcmp(), but without - * checking if the bytes are greater or lower. The order is also randomised - * using the RNG in order to further harden against side-channel - * attacks. - * - * \param buf1 First buffer to compare. - * \param buf2 Second buffer to compare against. - * \param num The length of the buffers in bytes. - * - * \deprecated Superseded by mbedtls_platform_memequal(), and is only an alias - * to it. - * - * \return 0 if the buffers were equal or an unspecified non-zero value - * otherwise. - */ -int mbedtls_platform_memcmp(const void *buf1, const void *buf2, size_t num); - -#endif -/** - * \brief Secure check if the buffers have the same data. - * - * This is a constant-time version of memcmp(), but without - * checking if the bytes are greater or lower. The order is also randomised - * using the RNG in order to further harden against side-channel - * attacks. - * - * \param buf1 First buffer to compare. - * \param buf2 Second buffer to compare against. - * \param num The length of the buffers in bytes. - * - * \return 0 if the buffers were equal or an unspecified non-zero value - * otherwise. - */ -int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num); - -/** - * \brief RNG-function for getting a random 32-bit integer. - * - * \return The generated random number. - */ -uint32_t mbedtls_platform_random_uint32(void); - -/** - * \brief RNG-function for getting a random in given range. - * - * This function is meant to provide a global RNG to be used - * throughout Mbed TLS for hardening the library. It is used - * for generating a random delay, random data or random offset - * for utility functions. It is not meant to be a - * cryptographically secure RNG, but provide an RNG for utility - * functions. - * - * \param num Max-value for the generated random number, exclusive. - * Must be greater than zero, otherwise an undefined behavior - * will occur on "num % 0". - * The generated number will be on range [0, num). - * - * \return The generated random number. - */ -uint32_t mbedtls_platform_random_in_range(uint32_t num); - -/** - * \brief Random delay function. - * - * Function implements a random delay by incrementing a local - * variable randomized number of times (busy-looping). - * - * Duration of the delay is random as number of variable increments - * is randomized. - * - * \note This function works only if the MBEDTLS_FI_COUNTERMEASURES flag - * is defined in the configuration. Otherwise, the function does - * nothing. - */ -void mbedtls_platform_random_delay(void); - -/** - * \brief RNG-function for getting a random buffer. - * - * \param buf Buffer for random data - * \param len Length of the buffer in bytes - * - */ -void mbedtls_platform_random_buf(uint8_t *buf, size_t len); - -#else - -/** - * \brief Securely zeroize a buffer - * - * The function is meant to wipe the data contained in a buffer so - * that it can no longer be recovered even if the program memory - * is later compromised. Call this function on sensitive data - * stored on the stack before returning from a function, and on - * sensitive data stored on the heap before freeing the heap - * object. - * - * It is extremely difficult to guarantee that calls to - * mbedtls_platform_zeroize() are not removed by aggressive - * compiler optimizations in a portable way. For this reason, Mbed - * TLS provides the configuration option - * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure - * mbedtls_platform_zeroize() to use a suitable implementation for - * their platform and needs - * - * \param buf Buffer to be zeroized - * \param len Length of the buffer in bytes - * - */ -void mbedtls_platform_zeroize(void *buf, size_t len); - -#endif - -#if defined(MBEDTLS_HAVE_TIME_DATE) -/** - * \brief Platform-specific implementation of gmtime_r() - * - * The function is a thread-safe abstraction that behaves - * similarly to the gmtime_r() function from Unix/POSIX. - * - * Mbed TLS will try to identify the underlying platform and - * make use of an appropriate underlying implementation (e.g. - * gmtime_r() for POSIX and gmtime_s() for Windows). If this is - * not possible, then gmtime() will be used. In this case, calls - * from the library to gmtime() will be guarded by the mutex - * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is - * enabled. It is recommended that calls from outside the library - * are also guarded by this mutex. - * - * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will - * unconditionally use the alternative implementation for - * mbedtls_platform_gmtime_r() supplied by the user at compile time. - * - * \param tt Pointer to an object containing time (in seconds) since the - * epoch to be converted - * \param tm_buf Pointer to an object where the results will be stored - * - * \return Pointer to an object of type struct tm on success, otherwise - * NULL - */ -struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, - struct tm *tm_buf); -#endif /* MBEDTLS_HAVE_TIME_DATE */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h index 8abc949cc6..2932d720f6 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc.h @@ -1,5 +1,8 @@ /* ecc.h - TinyCrypt interface to common ECC functions */ - +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ /* Copyright (c) 2014, Kenneth MacKay * All rights reserved. * @@ -25,7 +28,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * @@ -55,7 +57,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /** * @file * @brief -- Interface to common ECC functions. @@ -67,62 +68,43 @@ * Security: The curve NIST p-256 provides approximately 128 bits of security. * */ - #ifndef __TC_UECC_H__ #define __TC_UECC_H__ - #include - #ifdef __cplusplus extern "C" { #endif - +/* Return values for functions, chosen with large Hamming distances between + * them (especially to SUCESS) to mitigate the impact of fault injection + * attacks flipping a low number of bits. */ +#define UECC_SUCCESS 0xCD +#define UECC_FAILURE 0x52 +#define UECC_FAULT_DETECTED 0x3B /* Word size (4 bytes considering 32-bits architectures) */ #define uECC_WORD_SIZE 4 - /* setting max number of calls to prng: */ #ifndef uECC_RNG_MAX_TRIES #define uECC_RNG_MAX_TRIES 64 #endif - /* defining data types to store word and bit counts: */ -typedef int8_t wordcount_t; -typedef int16_t bitcount_t; +typedef int_fast8_t wordcount_t; +typedef int_fast16_t bitcount_t; /* defining data type for comparison result: */ -typedef int8_t cmpresult_t; +typedef int_fast8_t cmpresult_t; /* defining data type to store ECC coordinate/point in 32bits words: */ typedef unsigned int uECC_word_t; /* defining data type to store an ECC coordinate/point in 64bits words: */ typedef uint64_t uECC_dword_t; - /* defining masks useful for ecc computations: */ -#define HIGH_BIT_SET 0x80000000 -#define uECC_WORD_BITS 32 +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 #define uECC_WORD_BITS_SHIFT 5 -#define uECC_WORD_BITS_MASK 0x01F - +#define uECC_WORD_BITS_MASK 0x01F /* Number of words of 32 bits to represent an element of the the curve p-256: */ #define NUM_ECC_WORDS 8 /* Number of bytes to represent an element of the the curve p-256: */ -#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS) - -/* structure that represents an elliptic curve (e.g. p256):*/ -struct uECC_Curve_t; -typedef const struct uECC_Curve_t * uECC_Curve; -struct uECC_Curve_t { - wordcount_t num_words; - wordcount_t num_bytes; - bitcount_t num_n_bits; - uECC_word_t p[NUM_ECC_WORDS]; - uECC_word_t n[NUM_ECC_WORDS]; - uECC_word_t G[NUM_ECC_WORDS * 2]; - uECC_word_t b[NUM_ECC_WORDS]; - void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1, - uECC_Curve curve); - void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); - void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); -}; - +#define NUM_ECC_BYTES (uECC_WORD_SIZE * NUM_ECC_WORDS) +#define NUM_ECC_BITS 256 /* * @brief computes doubling of point ion jacobian coordinates, in place. * @param X1 IN/OUT -- x coordinate @@ -130,18 +112,7 @@ struct uECC_Curve_t { * @param Z1 IN/OUT -- z coordinate * @param curve IN -- elliptic curve */ -void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * Z1, uECC_Curve curve); - -/* - * @brief Computes x^3 + ax + b. result must not overlap x. - * @param result OUT -- x^3 + ax + b - * @param x IN -- value of x - * @param curve IN -- elliptic curve - */ -void x_side_default(uECC_word_t *result, const uECC_word_t *x, - uECC_Curve curve); - +void double_jacobian_default(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *Z1); /* * @brief Computes result = product % curve_p * from http://www.nsa.gov/ia/_files/nist-routines.pdf @@ -149,68 +120,30 @@ void x_side_default(uECC_word_t *result, const uECC_word_t *x, * @param product IN -- value to be reduced mod curve_p */ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product); - /* Bytes to words ordering: */ #define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e -#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a -#define BITS_TO_WORDS(num_bits) \ - ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) -#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) - -/* definition of curve NIST p-256: */ -static const struct uECC_Curve_t curve_secp256r1 = { - NUM_ECC_WORDS, - NUM_ECC_BYTES, - 256, /* num_n_bits */ { - BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), - BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), - BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) - }, { - BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), - BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), - BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) - }, { - BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), - BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), - BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), - BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), - - BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), - BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), - BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), - BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) - }, { - BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), - BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), - BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), - BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) - }, - &double_jacobian_default, - &x_side_default, - &vli_mmod_fast_secp256r1 -}; - -uECC_Curve uECC_secp256r1(void); - +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a +#define BITS_TO_WORDS(num_bits) ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) +#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) +extern const uECC_word_t curve_p[NUM_ECC_WORDS]; +extern const uECC_word_t curve_n[NUM_ECC_WORDS]; +extern const uECC_word_t curve_G[2 * NUM_ECC_WORDS]; +extern const uECC_word_t curve_b[NUM_ECC_WORDS]; /* * @brief Generates a random integer in the range 0 < random < top. * Both random and top have num_words words. * @param random OUT -- random integer in the range 0 < random < top * @param top IN -- upper limit * @param num_words IN -- number of words - * @return a random integer in the range 0 < random < top + * @return UECC_SUCCESS in case of success + * @return UECC_FAILURE upon failure */ -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words); - - +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, wordcount_t num_words); /* uECC_RNG_Function type * The RNG function should fill 'size' random bytes into 'dest'. It should - * return 1 if 'dest' was filled with random data, or 0 if the random data could - * not be generated. The filled-in values should be either truly random, or from - * a cryptographically-secure PRNG. + * return 'size' if 'dest' was filled with random data of 'size' length, or 0 + * if the random data could not be generated. The filled-in values should be + * either truly random, or from a cryptographically-secure PRNG. * * A correctly functioning RNG function must be set (using uECC_set_rng()) * before calling uECC_make_key() or uECC_sign(). @@ -222,12 +155,11 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, * POSIX-compliant system that supports /dev/random or /dev/urandom, you can * define uECC_POSIX to use the predefined RNG. */ -typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size); - +typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned int size); /* * @brief Set the function that will be used to generate random bytes. The RNG - * function should return 1 if the random data was generated, or 0 if the random - * data could not be generated. + * function should return 'size' if the random data of length 'size' was + * generated, or 0 if the random data could not be generated. * * @note On platforms where there is no predefined RNG function, this must be * called before uECC_make_key() or uECC_sign() are used. @@ -235,90 +167,65 @@ typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size); * @param rng_function IN -- function that will be used to generate random bytes */ void uECC_set_rng(uECC_RNG_Function rng_function); - /* * @brief provides current uECC_RNG_Function. * @return Returns the function that will be used to generate random bytes. */ uECC_RNG_Function uECC_get_rng(void); - /* * @brief computes the size of a private key for the curve in bytes. * @param curve IN -- elliptic curve * @return size of a private key for the curve in bytes. */ -int uECC_curve_private_key_size(uECC_Curve curve); - +int uECC_curve_private_key_size(void); /* * @brief computes the size of a public key for the curve in bytes. * @param curve IN -- elliptic curve * @return the size of a public key for the curve in bytes. */ -int uECC_curve_public_key_size(uECC_Curve curve); - +int uECC_curve_public_key_size(void); /* * @brief Compute the corresponding public key for a private key. * @param private_key IN -- The private key to compute the public key for * @param public_key OUT -- Will be filled in with the corresponding public key * @param curve - * @return Returns 1 if key was computed successfully, 0 if an error occurred. + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED */ -int uECC_compute_public_key(const uint8_t *private_key, - uint8_t *public_key, uECC_Curve curve); - +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key); /* * @brief Compute public-key. * @return corresponding public-key. * @param result OUT -- public-key * @param private_key IN -- private-key * @param curve IN -- elliptic curve + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED */ -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key, uECC_Curve curve); - -/* - * @brief Regularize the bitcount for the private key so that attackers cannot - * use a side channel attack to learn the number of leading zeros. - * @return Regularized k - * @param k IN -- private-key - * @param k0 IN/OUT -- regularized k - * @param k1 IN/OUT -- regularized k - * @param curve IN -- elliptic curve - */ -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve); - +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key); /* * @brief Point multiplication algorithm using Montgomery's ladder with co-Z * coordinates. See http://eprint.iacr.org/2011/338.pdf. + * Uses scalar regularization and coordinate randomization (if a global RNG + * function is set) in order to protect against some side channel attacks. * @note Result may overlap point. * @param result OUT -- returns scalar*point * @param point IN -- elliptic curve point * @param scalar IN -- scalar - * @param initial_Z IN -- initial value for z - * @param num_bits IN -- number of bits in scalar - * @param curve IN -- elliptic curve + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED */ -void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, - const uECC_word_t * scalar, const uECC_word_t * initial_Z, - bitcount_t num_bits, uECC_Curve curve); - +int EccPoint_mult_safer(uECC_word_t *result, const uECC_word_t *point, const uECC_word_t *scalar); /* * @brief Constant-time comparison to zero - secure way to compare long integers * @param vli IN -- very long integer * @param num_words IN -- number of words in the vli * @return 1 if vli == 0, 0 otherwise. */ -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); - +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli); /* * @brief Check if 'point' is the point at infinity * @param point IN -- elliptic curve point - * @param curve IN -- elliptic curve * @return if 'point' is the point at infinity, 0 otherwise. */ -uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); - +uECC_word_t EccPoint_isZero(const uECC_word_t *point); /* * @brief computes the sign of left - right, in constant time. * @param left IN -- left term to be compared @@ -326,9 +233,7 @@ uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); * @param num_words IN -- number of words * @return the sign of left - right */ -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right); /* * @brief computes sign of left - right, not in constant time. * @note should not be used if inputs are part of a secret @@ -337,9 +242,7 @@ cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, * @param num_words IN -- number of words * @return the sign of left - right */ -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right); /* * @brief Computes result = (left - right) % mod. * @note Assumes that (left < mod) and (right < mod), and that result does not @@ -350,10 +253,7 @@ cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *righ * @param mod IN -- mod * @param num_words IN -- number of words */ -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or * P => P', Q => P + Q @@ -364,9 +264,7 @@ void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, * @param Y2 IN -- y coordinate of Q * @param curve IN -- elliptic curve */ -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, - uECC_word_t * Y2, uECC_Curve curve); - +void XYcZ_add(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2); /* * @brief Computes (x1 * z^2, y1 * z^3) * @param X1 IN -- previous x1 coordinate @@ -374,9 +272,7 @@ void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, * @param Z IN -- z value * @param curve IN -- elliptic curve */ -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve); - +void apply_z(uECC_word_t *X1, uECC_word_t *Y1, const uECC_word_t *const Z); /* * @brief Check if bit is set. * @return Returns nonzero if bit 'bit' of vli is set. @@ -387,7 +283,6 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, * of 4 uECC_word_t elements. */ uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); - /* * @brief Computes result = product % mod, where product is 2N words long. * @param result OUT -- product % mod @@ -395,9 +290,7 @@ uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); * @param num_words IN -- number of words * @warning Currently only designed to work for curve_p or curve_n. */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words); - +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, const uECC_word_t *mod); /* * @brief Computes modular product (using curve->mmod_fast) * @param result OUT -- (left * right) mod % curve_p @@ -405,9 +298,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, * @param right IN -- right term in product * @param curve IN -- elliptic curve */ -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve); - +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right); /* * @brief Computes result = left - right. * @note Can modify in place. @@ -417,19 +308,15 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, * @param num_words IN -- number of words * @return borrow */ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words); - +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right); /* * @brief Constant-time comparison function(secure way to compare long ints) * @param left IN -- left term in comparison * @param right IN -- right term in comparison * @param num_words IN -- number of words - * @return Returns 0 if left == right, 1 otherwise. + * @return Returns 0 if left == right, non-zero otherwise. */ -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); - +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right); /* * @brief Computes (left * right) % mod * @param result OUT -- (left * right) % mod @@ -438,10 +325,7 @@ uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, * @param mod IN -- mod * @param num_words IN -- number of words */ -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Computes (1 / input) % mod * @note All VLIs are the same size. @@ -451,18 +335,14 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, * @param mod IN -- mod * @param num_words -- number of words */ -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words); - +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, const uECC_word_t *mod); /* * @brief Sets dest = src. * @param dest OUT -- destination buffer * @param src IN -- origin buffer * @param num_words IN -- number of words */ -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words); - +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src); /* * @brief Computes (left + right) % mod. * @note Assumes that (left < mod) and right < mod), and that result does not @@ -473,26 +353,20 @@ void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, * @param mod IN -- mod * @param num_words IN -- number of words */ -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words); - +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Counts the number of bits required to represent vli. * @param vli IN -- very long integer * @param max_words IN -- number of words * @return number of bits in given vli */ -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words); - +bitcount_t uECC_vli_numBits(const uECC_word_t *vli); /* * @brief Erases (set to 0) vli * @param vli IN -- very long integer * @param num_words IN -- number of words */ -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); - +void uECC_vli_clear(uECC_word_t *vli); /* * @brief check if it is a valid point in the curve * @param point IN -- point to be checked @@ -502,8 +376,7 @@ void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); * @exception returns -2 if x or y is smaller than p, * @exception returns -3 if y^2 != x^3 + ax + b. */ -int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); - +int uECC_valid_point(const uECC_word_t *point); /* * @brief Check if a public key is valid. * @param public_key IN -- The public key to be checked. @@ -518,28 +391,22 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); * time computing a shared secret or verifying a signature using an invalid * public key. */ -int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); - - /* +int uECC_valid_public_key(const uint8_t *public_key); +/* * @brief Converts an integer in uECC native format to big-endian bytes. * @param bytes OUT -- bytes representation * @param num_bytes IN -- number of bytes * @param native IN -- uECC native representation */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native); - +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const unsigned int *native); /* * @brief Converts big-endian bytes to an integer in uECC native format. * @param native OUT -- uECC native representation * @param bytes IN -- bytes representation * @param num_bytes IN -- number of bytes */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes); - +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, int num_bytes); #ifdef __cplusplus } #endif - -#endif /* __TC_UECC_H__ */ +#endif /* __TC_UECC_H__ */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h index b828e195db..1f84359022 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dh.h @@ -1,5 +1,8 @@ /* ecc_dh.h - TinyCrypt interface to EC-DH implementation */ - +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ /* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. @@ -26,7 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /* Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +57,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /** * @file * @brief -- Interface to EC-DH implementation. @@ -65,20 +66,15 @@ * * Security: The curve NIST p-256 provides approximately 128 bits of security. */ - #ifndef __TC_ECC_DH_H__ #define __TC_ECC_DH_H__ - #include - #ifdef __cplusplus extern "C" { #endif - /** * @brief Create a public/private key pair. - * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully - * returns TC_CRYPTO_FAIL (0) if error while generating key pair + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED * * @param p_public_key OUT -- Will be filled in with the public key. Must be at * least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key @@ -91,25 +87,20 @@ extern "C" { * @warning A cryptographically-secure PRNG function must be set (using * uECC_set_rng()) before calling uECC_make_key(). */ -int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve); - +int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key); #ifdef ENABLE_TESTS - /** * @brief Create a public/private key pair given a specific d. * * @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to * uECC_make_key() function for real applications. */ -int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, - unsigned int *d, uECC_Curve curve); +int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, unsigned int *d); #endif - /** * @brief Compute a shared secret given your secret key and someone else's * public key. - * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully - * returns TC_CRYPTO_FAIL (0) otherwise + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED * * @param p_secret OUT -- Will be filled in with the shared secret value. Must be * the same size as the curve size (for curve secp256r1, secret must be 32 bytes @@ -121,11 +112,8 @@ int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key, * input of a recommended Key Derivation Function (see NIST SP 800-108) in * order to produce a cryptographically secure symmetric key. */ -int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key, - uint8_t *p_secret, uECC_Curve curve); - +int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key, uint8_t *p_secret); #ifdef __cplusplus } #endif - -#endif /* __TC_ECC_DH_H__ */ +#endif /* __TC_ECC_DH_H__ */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h index aca00bc95e..46d96612af 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_dsa.h @@ -1,5 +1,8 @@ /* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */ - +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ /* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. @@ -26,7 +29,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * @@ -56,7 +58,6 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /** * @file * @brief -- Interface to EC-DSA implementation. @@ -74,20 +75,15 @@ * the same hash as the signer and pass it to this function along with * the signer's public key and the signature values (r and s). */ - #ifndef __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__ - #include - #ifdef __cplusplus extern "C" { #endif - /** * @brief Generate an ECDSA signature for a given hash value. - * @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully - * returns TC_CRYPTO_FAIL (0) if an error occurred. + * @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED * * @param p_private_key IN -- Your private key. * @param p_message_hash IN -- The hash of the message to sign. @@ -102,23 +98,22 @@ extern "C" { * @note side-channel countermeasure: algorithm strengthened against timing * attack. */ -int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, - unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve); - +int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash, unsigned p_hash_size, uint8_t *p_signature); #ifdef ENABLE_TESTS /* * THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY. * Refer to uECC_sign() function for real applications. */ -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned int hash_size, uECC_word_t *k, uint8_t *signature, - uECC_Curve curve); +int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned int hash_size, + uECC_word_t *k, + uint8_t *signature); #endif - /** * @brief Verify an ECDSA signature. - * @return returns TC_SUCCESS (1) if the signature is valid - * returns TC_FAIL (0) if the signature is invalid. + * @return returns UECC_SUCCESS if the signature is valid + * returns UECC_FAILURE if the signature is invalid. * * @param p_public_key IN -- The signer's public key. * @param p_message_hash IN -- The hash of the signed data. @@ -129,11 +124,11 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, * signer and pass it to this function along with the signer's public key and * the signature values (hash_size and signature). */ -int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash, - unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve); - +int uECC_verify(const uint8_t *p_public_key, + const uint8_t *p_message_hash, + unsigned int p_hash_size, + const uint8_t *p_signature); #ifdef __cplusplus } #endif - -#endif /* __TC_ECC_DSA_H__ */ +#endif /* __TC_ECC_DSA_H__ */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h new file mode 100644 index 0000000000..a9eff6f9a5 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h @@ -0,0 +1,13 @@ +#ifndef TINYCRYPT_PLATFORM_UTIL_H +#define TINYCRYPT_PLATFORM_UTIL_H + +#include +#include + +#if defined(SL_MBEDTLS_USE_TINYCRYPT) +void mbedtls_platform_random_buf(uint8_t *buf, size_t len); +void *mbedtls_platform_memset(void *, int, size_t); +void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); +#endif // defined(SL_MBEDTLS_USE_TINYCRYPT) + +#endif // TINYCRYPT_PLATFORM_UTIL_H \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h index 6b7b0abf9b..bab5c3202e 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h @@ -41,7 +41,6 @@ #include #include -#include #ifdef __cplusplus extern "C" { @@ -70,31 +69,6 @@ unsigned int _copy(uint8_t *to, unsigned int to_len, */ void _set(void *to, uint8_t val, unsigned int len); -/** - * @brief Set the value 'val' into the buffer 'to', 'len' times, in a way - * which does not risk getting optimized out by the compiler - * In cases where the compiler does not set __GNUC__ and where the - * optimization level removes the memset, it may be necessary to - * implement a _set_secure function and define the - * TINYCRYPT_ARCH_HAS_SET_SECURE, which then can ensure that the - * memset does not get optimized out. - * - * @param to OUT -- destination buffer - * @param val IN -- value to be set in 'to' - * @param len IN -- number of times the value will be copied - */ -#ifdef TINYCRYPT_ARCH_HAS_SET_SECURE -extern void _set_secure(void *to, uint8_t val, unsigned int len); -#else /* ! TINYCRYPT_ARCH_HAS_SET_SECURE */ -static inline void _set_secure(void *to, uint8_t val, unsigned int len) -{ - (void) memset(to, val, len); -#ifdef __GNUC__ - __asm__ __volatile__("" :: "g"(to) : "memory"); -#endif /* __GNUC__ */ -} -#endif /* TINYCRYPT_ARCH_HAS_SET_SECURE */ - /* * @brief AES specific doubling function, which utilizes * the finite field used by AES. diff --git a/matter/mbedtls/tinycrypt/src/cbc_mode.c b/matter/mbedtls/tinycrypt/src/cbc_mode.c index ae20af1a70..62d7879ebd 100644 --- a/matter/mbedtls/tinycrypt/src/cbc_mode.c +++ b/matter/mbedtls/tinycrypt/src/cbc_mode.c @@ -91,7 +91,7 @@ int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, outlen == 0 || (inlen % TC_AES_BLOCK_SIZE) != 0 || (outlen % TC_AES_BLOCK_SIZE) != 0 || - outlen != inlen) { + outlen != inlen - TC_AES_BLOCK_SIZE) { return TC_CRYPTO_FAIL; } @@ -101,7 +101,7 @@ int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, * that would not otherwise be possible. */ p = iv; - for (n = m = 0; n < outlen; ++n) { + for (n = m = 0; n < inlen; ++n) { if ((n % TC_AES_BLOCK_SIZE) == 0) { (void)tc_aes_decrypt(buffer, in, sched); in += TC_AES_BLOCK_SIZE; diff --git a/matter/mbedtls/tinycrypt/src/cmac_mode.c b/matter/mbedtls/tinycrypt/src/cmac_mode.c index 22adf2089f..96d147e809 100644 --- a/matter/mbedtls/tinycrypt/src/cmac_mode.c +++ b/matter/mbedtls/tinycrypt/src/cmac_mode.c @@ -36,7 +36,7 @@ #include /* max number of calls until change the key (2^48).*/ -static const uint64_t MAX_CALLS = ((uint64_t)1 << 48); +const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); /* * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte diff --git a/matter/mbedtls/tinycrypt/src/ecc.c b/matter/mbedtls/tinycrypt/src/ecc.c index 46080bf619..d2d46bb603 100644 --- a/matter/mbedtls/tinycrypt/src/ecc.c +++ b/matter/mbedtls/tinycrypt/src/ecc.c @@ -1,5 +1,8 @@ /* ecc.c - TinyCrypt implementation of common ECC functions */ - +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ /* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. @@ -28,16 +31,16 @@ * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -51,11 +54,99 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#if defined(SL_MBEDTLS_USE_TINYCRYPT) #include -#include +#include "mbedtls/platform_util.h" +#include "mbedtls/sha256.h" #include - +#include "mbedtls/platform_util.h" +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM +#ifndef asm +#define asm __asm +#endif +#endif /* MBEDTLS_OPTIMIZE_TINYCRYPT_ASM */ + +#include "mbedtls/compat-2.x.h" + +/* Parameters for curve NIST P-256 aka secp256r1 */ +const uECC_word_t curve_p[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) }; +const uECC_word_t curve_n[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) }; +const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = { + BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) +}; +const uECC_word_t curve_b[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }; +static int uECC_update_param_sha256(mbedtls_sha256_context *ctx, const uECC_word_t val[NUM_ECC_WORDS]) +{ + uint8_t bytes[NUM_ECC_BYTES]; + uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val); + return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES); +} +static int uECC_compute_param_sha256(unsigned char output[32]) +{ + int ret = UECC_FAILURE; + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) { + goto exit; + } + if (uECC_update_param_sha256(&ctx, curve_p) != 0 || uECC_update_param_sha256(&ctx, curve_n) != 0 + || uECC_update_param_sha256(&ctx, curve_G) != 0 || uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 + || uECC_update_param_sha256(&ctx, curve_b) != 0) { + goto exit; + } + if (mbedtls_sha256_finish_ret(&ctx, output) != 0) { + goto exit; + } + ret = UECC_SUCCESS; +exit: + mbedtls_sha256_free(&ctx); + return ret; +} +/* + * Check integrity of curve parameters. + * Return 0 if everything's OK, non-zero otherwise. + */ +static int uECC_check_curve_integrity(void) +{ + unsigned char computed[32]; + static const unsigned char reference[32] = { + 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1, 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92, + 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6, 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49, + }; + int diff = 0; + unsigned char tmp1, tmp2; + volatile unsigned i; + if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) { + return UECC_FAILURE; + } + for (i = 0; i < 32; i++) { + /* make sure the order of volatile accesses is well-defined */ + tmp1 = computed[i]; + tmp2 = reference[i]; + diff |= tmp1 ^ tmp2; + } + /* i should be 32 */ + mbedtls_platform_random_delay(); + diff |= i ^ 32; + return diff; +} /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform * has access to enough entropy in order to feed the PRNG regularly. */ #if default_RNG_defined @@ -63,880 +154,1418 @@ static uECC_RNG_Function g_rng_function = &default_CSPRNG; #else static uECC_RNG_Function g_rng_function = 0; #endif - void uECC_set_rng(uECC_RNG_Function rng_function) { - g_rng_function = rng_function; + g_rng_function = rng_function; } - uECC_RNG_Function uECC_get_rng(void) { - return g_rng_function; + return g_rng_function; } - -int uECC_curve_private_key_size(uECC_Curve curve) +int uECC_curve_private_key_size(void) { - return BITS_TO_BYTES(curve->num_n_bits); + return BITS_TO_BYTES(NUM_ECC_BITS); } - -int uECC_curve_public_key_size(uECC_Curve curve) +int uECC_curve_public_key_size(void) { - return 2 * curve->num_bytes; + return 2 * NUM_ECC_BYTES; } - -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +__asm void uECC_vli_clear(uECC_word_t *vli) +{ +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if !defined __thumb__ || __TARGET_ARCH_THUMB < 4 + MOVS r1, #0 MOVS r2, #0 STMIA r0 !, { r1, r2 } STMIA r0 !, { r1, r2 } STMIA r0 !, { r1, r2 } STMIA r0 !, + { r1, r2 } BX lr +#else + MOVS r1, #0 STRD r1, r1, + [r0, #0] // Only Thumb2 STRD can store same reg twice, not ARM + STRD r1, + r1, [r0, #8] STRD r1, r1, [r0, #16] STRD r1, r1, [r0, #24] BX lr +#endif +} +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ +void uECC_vli_clear(uECC_word_t *vli) { - wordcount_t i; - for (i = 0; i < num_words; ++i) { - vli[i] = 0; - } +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if !defined __thumb__ || !defined __thumb2__ + register uECC_word_t *r0 asm("r0") = vli; + register uECC_word_t r1 asm("r1") = 0; + register uECC_word_t r2 asm("r2") = 0; + asm volatile(".syntax unified \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + ".syntax divided \n\t" + : "+r"(r0) + : "r"(r1), "r"(r2) + : "memory" +#else + register uECC_word_t *r0 asm("r0") = vli; + register uECC_word_t r1 asm("r1") = 0; + asm volatile("STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM + "STRD r1,r1,[r0,#8] \n\t" + "STRD r1,r1,[r0,#16] \n\t" + "STRD r1,r1,[r0,#24] \n\t" + : + : "r"(r0), "r"(r1) + : "memory" +#endif + ); } - -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) +#else +void uECC_vli_clear(uECC_word_t *vli) { - uECC_word_t bits = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - bits |= vli[i]; - } - return (bits == 0); + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + vli[i] = 0; + } } - +#endif +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli){ +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + LDMIA r0 !, { r1, r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0 !, { r2, r3 } ORRS r1, r2 ORRS r1, + r3 LDMIA r0, { r0, r2, r3 } ORRS r1, r0 ORRS r1, r2 ORRS r1, r3 RSBS r1, r1, +# 0 // C set if zero + MOVS r0, +# 0 ADCS r0, + r0 BX lr +#else + LDMIA r0 !, + { r1, r2, r3, ip } ORRS r1, + r2 ORRS r1, + r3 ORRS r1, + ip LDMIA r0, + { r0, r2, r3, ip } ORRS r1, + r0 ORRS r1, + r2 ORRS r1, + r3 ORRS r1, + ip +#ifdef __ARM_FEATURE_CLZ + CLZ r0, + r1 // 32 if zero + LSRS r0, + r0, +# 5 +#else + RSBS r1, + r1, +# 0 // C set if zero + MOVS r0, +# 0 ADCS r0, + r0 +#endif + BX lr +#endif +} +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) +{ + uECC_word_t ret; +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if defined __thumb__ && !defined __thumb2__ + register uECC_word_t r1 asm("r1"); + register uECC_word_t r2 asm("r2"); + register uECC_word_t r3 asm("r3"); + asm volatile(".syntax unified \n\t" + "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "LDMIA %[vli]!,{%[r2],%[r3]} \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t" + "ORRS %[r1],%[vli] \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "RSBS %[r1],%[r1],#0 \n\t" // C set if zero + "MOVS %[ret],#0 \n\t" + "ADCS %[ret],r0 \n\t" + ".syntax divided \n\t" + : [ret] "=r"(ret), [r1] "=r"(r1), [r2] "=r"(r2), [r3] "=r"(r3) + : [vli] "[ret]"(vli) + : "cc", "memory"); +#else + register uECC_word_t r1 asm("r1"); + register uECC_word_t r2 asm("r2"); + register uECC_word_t r3 asm("r3"); + register uECC_word_t ip asm("ip"); + asm volatile("LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "ORRS %[r1],%[ip] \n\t" + "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t" + "ORRS %[r1],%[vli] \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "ORRS %[r1],%[ip] \n\t" +#if __ARM_ARCH >= 5 + "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero + "LSRS %[ret],%[ret],#5 \n\t" +#else + "RSBS %[r1],%[r1],#0 \n\t" // C set if zero + "MOVS %[ret],#0 \n\t" + "ADCS %[ret],r0 \n\t" +#endif + : [ret] "=r"(ret), [r1] "=r"(r1), [r2] "=r"(r2), [r3] "=r"(r3), [ip] "=r"(ip) + : [vli] "[ret]"(vli) + : "cc", "memory"); +#endif + return ret; +} +#else +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) +{ + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + bits |= vli[i]; + } + return (bits == 0); +} +#endif uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { - return (vli[bit >> uECC_WORD_BITS_SHIFT] & - ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); + return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); } - /* Counts the number of words in vli. */ -static wordcount_t vli_numDigits(const uECC_word_t *vli, - const wordcount_t max_words) +static wordcount_t vli_numDigits(const uECC_word_t *vli) { - - wordcount_t i; - /* Search from the end until we find a non-zero digit. We do it in reverse + wordcount_t i; + /* Search from the end until we find a non-zero digit. We do it in reverse * because we expect that most digits will be nonzero. */ - for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { - } - - return (i + 1); + for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) { + } + return (i + 1); } - -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words) +bitcount_t uECC_vli_numBits(const uECC_word_t *vli) { - - uECC_word_t i; - uECC_word_t digit; - - wordcount_t num_digits = vli_numDigits(vli, max_words); - if (num_digits == 0) { - return 0; - } - - digit = vli[num_digits - 1]; - for (i = 0; digit; ++i) { - digit >>= 1; - } - - return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); + uECC_word_t i; + uECC_word_t digit; + wordcount_t num_digits = vli_numDigits(vli); + if (num_digits == 0) { + return 0; + } + digit = vli[num_digits - 1]; +#if defined __GNUC__ || defined __clang__ || defined __CC_ARM + i = uECC_WORD_BITS - __builtin_clz(digit); +#else + for (i = 0; digit; ++i) { + digit >>= 1; + } +#endif + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); } - -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words) +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src) { - wordcount_t i; - - for (i = 0; i < num_words; ++i) { - dest[i] = src[i]; - } + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + dest[i] = src[i]; + } } - -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, - const uECC_word_t *right, - wordcount_t num_words) +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right) { - wordcount_t i; - - for (i = num_words - 1; i >= 0; --i) { - if (left[i] > right[i]) { - return 1; - } else if (left[i] < right[i]) { - return -1; - } - } - return 0; + wordcount_t i; + for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; } - -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right) { - - uECC_word_t diff = 0; - wordcount_t i; - - for (i = num_words - 1; i >= 0; --i) { - diff |= (left[i] ^ right[i]); - } - return !(diff == 0); + uECC_word_t diff = 0; + uECC_word_t flow_monitor = 0; + uECC_word_t tmp1, tmp2; + volatile int i; + /* Start from a random location and check the correct number of iterations */ + int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS); + for (i = start_offset; i < NUM_ECC_WORDS; ++i) { + tmp1 = left[i]; + tmp2 = right[i]; + flow_monitor++; + diff |= (tmp1 ^ tmp2); + } + for (i = 0; i < start_offset; ++i) { + tmp1 = left[i]; + tmp2 = right[i]; + flow_monitor++; + diff |= (tmp1 ^ tmp2); + } + /* Random delay to increase security */ + mbedtls_platform_random_delay(); + /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */ + return (diff | (flow_monitor ^ NUM_ECC_WORDS)); } - uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) { - return (p_true*(cond)) | (p_false*(!cond)); + return (p_true * (cond)) | (p_false * (cond ^ 1)); } - /* Computes result = left - right, returning borrow, in constant time. * Can modify in place. */ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - uECC_word_t diff = left[i] - right[i] - borrow; - uECC_word_t val = (diff > left[i]); - borrow = cond_set(val, borrow, (diff != left[i])); - - result[i] = diff; - } - return borrow; +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +{ +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH{ r4 - r6, lr } FRAME PUSH{ r4 - r6, lr } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SUBS r3, r5 SBCS r4, + r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, + { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, + { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, { r3, r4 } SBCS r0, + r0 // r0 := r0 - r0 - borrow = -borrow + RSBS r0, + r0, +# 0 // r0 := borrow + POP{ r4 - r6, pc } +#else + PUSH{ r4 - r8, lr } FRAME PUSH{ r4 - r8, lr } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, { r7, r8, r12, lr } SUBS r3, + r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, lr STMIA r0 !, { r3 - r6 } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, + { r7, r8, r12, lr } SBCS r3, r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, lr STMIA r0 !, { r3 - r6 } SBCS r0, + r0 // r0 := r0 - r0 - borrow = -borrow + RSBS r0, + r0, +# 0 // r0 := borrow + POP + { + r4 - r8, pc + } +#endif } - +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +{ +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif + register uECC_word_t *r0 asm("r0") = result; + register const uECC_word_t *r1 asm("r1") = left; + register const uECC_word_t *r2 asm("r2") = right; + asm volatile( +#if defined __thumb__ && !defined __thumb2__ + ".syntax unified \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "SUBS r3,r5 \n\t" + "SBCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "SBCS r3,r5 \n\t" + "SBCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "SBCS r3,r5 \n\t" + "SBCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "SBCS r3,r5 \n\t" + "SBCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow + "RSBS r0,r0,#0 \n\t" // r0 := borrow + ".syntax divided \n\t" + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "r4", "r5", "r6", "cc", "memory" +#else + "LDMIA r1!,{r3-r6} \n\t" + "LDMIA r2!,{r7,r8,r12,lr} \n\t" + "SUBS r3,r7 \n\t" + "SBCS r4,r8 \n\t" + "SBCS r5,r12 \n\t" + "SBCS r6,lr \n\t" + "STMIA r0!,{r3-r6} \n\t" + "LDMIA r1!,{r3-r6} \n\t" + "LDMIA r2!,{r7,r8,r12,lr} \n\t" + "SBCS r3,r7 \n\t" + "SBCS r4,r8 \n\t" + "SBCS r5,r12 \n\t" + "SBCS r6,lr \n\t" + "STMIA r0!,{r3-r6} \n\t" + "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow + "RSBS r0,r0,#0 \n\t" // r0 := borrow + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" +#endif + ); + return (uECC_word_t)r0; +} +#else +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +{ + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + uECC_word_t val = (diff > left[i]); + borrow = cond_set(val, borrow, (diff != left[i])); + result[i] = diff; + } + return borrow; +} +#endif /* Computes result = left + right, returning carry, in constant time. * Can modify in place. */ -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - uECC_word_t carry = 0; - wordcount_t i; - for (i = 0; i < num_words; ++i) { - uECC_word_t sum = left[i] + right[i] + carry; - uECC_word_t val = (sum < left[i]); - carry = cond_set(val, carry, (sum != left[i])); - result[i] = sum; - } - return carry; +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +{ +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH{ r4 - r6, lr } FRAME PUSH{ r4 - r6, lr } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADDS r3, r5 ADCS r4, + r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, + { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, + { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, { r3, r4 } MOVS r0, +# 0 // does not affect C flag + ADCS r0, + r0 // r0 := 0 + 0 + C = carry + POP{ r4 - r6, pc } +#else + PUSH{ r4 - r8, lr } FRAME PUSH{ r4 - r8, lr } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, { r7, r8, r12, lr } ADDS r3, + r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, lr STMIA r0 !, { r3 - r6 } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, + { r7, r8, r12, lr } ADCS r3, r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, lr STMIA r0 !, { r3 - r6 } MOVS r0, +# 0 // does not affect C flag + ADCS r0, + r0 // r0 := 0 + 0 + C = carry + POP + { + r4 - r8, pc + } +#endif } - -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); - uECC_word_t equal = uECC_vli_isZero(tmp, num_words); - return (!equal - 2 * neg); + register uECC_word_t *r0 asm("r0") = result; + register const uECC_word_t *r1 asm("r1") = left; + register const uECC_word_t *r2 asm("r2") = right; + asm volatile( +#if defined __thumb__ && !defined __thumb2__ + ".syntax unified \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "ADDS r3,r5 \n\t" + "ADCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "ADCS r3,r5 \n\t" + "ADCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "ADCS r3,r5 \n\t" + "ADCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "LDMIA r1!,{r3,r4} \n\t" + "LDMIA r2!,{r5,r6} \n\t" + "ADCS r3,r5 \n\t" + "ADCS r4,r6 \n\t" + "STMIA r0!,{r3,r4} \n\t" + "MOVS r0,#0 \n\t" // does not affect C flag + "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry + ".syntax divided \n\t" + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "r4", "r5", "r6", "cc", "memory" +#else + "LDMIA r1!,{r3-r6} \n\t" + "LDMIA r2!,{r7,r8,r12,lr} \n\t" + "ADDS r3,r7 \n\t" + "ADCS r4,r8 \n\t" + "ADCS r5,r12 \n\t" + "ADCS r6,lr \n\t" + "STMIA r0!,{r3-r6} \n\t" + "LDMIA r1!,{r3-r6} \n\t" + "LDMIA r2!,{r7,r8,r12,lr} \n\t" + "ADCS r3,r7 \n\t" + "ADCS r4,r8 \n\t" + "ADCS r5,r12 \n\t" + "ADCS r6,lr \n\t" + "STMIA r0!,{r3-r6} \n\t" + "MOVS r0,#0 \n\t" // does not affect C flag + "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" +#endif + ); + return (uECC_word_t)r0; +} +#else +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +{ + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + uECC_word_t val = (sum < left[i]); + carry = cond_set(val, carry, (sum != left[i])); + result[i] = sum; + } + return carry; +} +#endif +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right) +{ + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t neg = uECC_vli_sub(tmp, left, right); + uECC_word_t equal = uECC_vli_isZero(tmp); + return ((equal ^ 1) - 2 * neg); } - /* Computes vli = vli >> 1. */ -static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +static __asm void uECC_vli_rshift1(uECC_word_t *vli) { - uECC_word_t *end = vli; - uECC_word_t carry = 0; - - vli += num_words; - while (vli-- > end) { - uECC_word_t temp = *vli; - *vli = (temp >> 1) | carry; - carry = temp << (uECC_WORD_BITS - 1); - } +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + // RRX instruction is not available, so although we + // can use C flag, it's not that effective. Does at + // least save one working register, meaning we don't need stack + MOVS r3, +# 0 // initial carry = 0 + MOVS r2, +#__cpp(4 * (NUM_ECC_WORDS - 1)) 01 LDR r1, [r0, r2] LSRS r1, r1, +# 1 // r2 = word >> 1 + ORRS r1, + r3 // merge in the previous carry + STR r1, + [r0, r2] ADCS r3, + r3 // put C into bottom bit of r3 + LSLS r3, + r3, +# 31 // shift it up to the top ready for next word + SUBS r2, r2, #4 BPL % B01 BX lr +#else +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif + // Smooth multiword operation, lots of 32-bit instructions + ADDS r0, #32 LDMDB r0, { r1 - r3, ip } LSRS ip, ip, #1 RRXS r3, r3 RRXS r2, r2 RRXS r1, r1 STMDB r0 !, + { r1 - r3, ip } LDMDB r0, { r1 - r3, ip } RRXS ip, ip RRXS r3, r3 RRXS r2, r2 RRX r1, r1 STMDB r0 !, + { r1 - r3, ip } BX lr +#endif } - -static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, - uECC_word_t *r1, uECC_word_t *r2) +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__ +static void uECC_vli_rshift1(uECC_word_t *vli) { - - uECC_dword_t p = (uECC_dword_t)a * b; - uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; - r01 += p; - *r2 += (r01 < p); - *r1 = r01 >> uECC_WORD_BITS; - *r0 = (uECC_word_t)r01; - + register uECC_word_t *r0 asm("r0") = vli; +#if NUM_ECC_WORDS != 8 +#error adjust ARM assembly to handle NUM_ECC_WORDS != 8 +#endif + asm volatile("ADDS r0,#32 \n\t" + "LDMDB r0,{r1-r3,ip} \n\t" + "LSRS ip,ip,#1 \n\t" + "RRXS r3,r3 \n\t" + "RRXS r2,r2 \n\t" + "RRXS r1,r1 \n\t" + "STMDB r0!,{r1-r3,ip} \n\t" + "LDMDB r0,{r1-r3,ip} \n\t" + "RRXS ip,ip \n\t" + "RRXS r3,r3 \n\t" + "RRXS r2,r2 \n\t" + "RRX r1,r1 \n\t" + "STMDB r0!,{r1-r3,ip} \n\t" + : "+r"(r0) + : + : "r1", "r2", "r3", "ip", "cc", "memory"); } - -/* Computes result = left * right. Result must be 2 * num_words long. */ -static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) +#else +static void uECC_vli_rshift1(uECC_word_t *vli) { - - uECC_word_t r0 = 0; - uECC_word_t r1 = 0; - uECC_word_t r2 = 0; - wordcount_t i, k; - - /* Compute each digit of result in sequence, maintaining the carries. */ - for (k = 0; k < num_words; ++k) { - - for (i = 0; i <= k; ++i) { - muladd(left[i], right[k - i], &r0, &r1, &r2); - } - - result[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - - for (k = num_words; k < num_words * 2 - 1; ++k) { - - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], &r0, &r1, &r2); - } - result[k] = r0; - r0 = r1; - r1 = r2; - r2 = 0; - } - result[num_words * 2 - 1] = r0; + uECC_word_t *end = vli; + uECC_word_t carry = 0; + vli += NUM_ECC_WORDS; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } } - -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) +#endif +/* Compute a * b + r, where r is a triple-word with high-order word r[2] and + * low-order word r[0], and store the result in the same triple-word. + * + * r[2..0] = a * b + r[2..0]: + * [in] a, b: operands to be multiplied + * [in] r: 3 words of operand to add + * [out] r: 3 words of result + */ +#if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM +static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) +{ +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH{ r4 - r5 } FRAME PUSH{ r4 - r5 } // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 + // Separate operands into halfwords + UXTH r3, + r0 // r3 := a.lo + LSRS r4, + r0, +# 16 // r4 := a.hi + UXTH r5, + r1 // r5 := b.lo + LSRS r1, + r1, +# 16 // r1 := b.hi + // Multiply halfword pairs + MOVS r0, r3 MULS r0, r5, + r0 // r0 := a.lo * b.lo + MULS r3, + r1, + r3 // r3 := a.lo * b.hi + MULS r5, + r4, + r5 // r5 := a.hi * b.lo + MULS r1, + r4, + r1 // r1 := a.hi * b.hi + // Split, shift and add a.lo * b.hi + LSRS r4, + r3, +# 16 // r4 := (a.lo * b.hi).hi + LSLS r3, r3, +# 16 // r3 := (a.lo * b.hi).lo + ADDS r0, r0, + r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + ADCS r1, + r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry + // Split, shift and add a.hi * b.lo + LSRS r4, + r5, +# 16 // r4 := (a.hi * b.lo).hi + LSLS r5, r5, +# 16 // r5 := (a.hi * b.lo).lo + ADDS r0, r0, + r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo + ADCS r1, + r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries + // Finally add r[] + LDMIA r2 !, + { r3, r4, r5 } ADDS r3, r3, r0 ADCS r4, r1 MOVS r0, #0 ADCS r5, r0 SUBS r2, #12 STMIA r2 !, + { r3, r4, r5 } POP{ r4 - r5 } FRAME POP{ r4 - r5 } BX lr +#else + UMULL r3, ip, r0, + r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn + LDMIA r2, + { r0, r1 } ADDS r0, r0, r3 LDR r3, [r2, #8] ADCS r1, r1, ip ADC r3, r3, #0 STMIA r2 !, { r0, r1, r3 } BX lr +#endif +} +#elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ +static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) +{ + register uECC_word_t r0 asm("r0") = a; + register uECC_word_t r1 asm("r1") = b; + register uECC_word_t *r2 asm("r2") = r; + asm volatile( +#if defined __thumb__ && !defined(__thumb2__) + ".syntax unified \n\t" + // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 + // Separate operands into halfwords + "UXTH r3,r0 \n\t" // r3 := a.lo + "LSRS r4,r0,#16 \n\t" // r4 := a.hi + "UXTH r5,r1 \n\t" // r5 := b.lo + "LSRS r1,r1,#16 \n\t" // r1 := b.hi + // Multiply halfword pairs + "MOVS r0,r3 \n\t" + "MULS r0,r5,r0 \n\t" // r0 := a.lo * b.lo + "MULS r3,r1,r3 \n\t" // r3 := a.lo * b.hi + "MULS r5,r4,r5 \n\t" // r5 := a.hi * b.lo + "MULS r1,r4,r1 \n\t" // r1 := a.hi * b.hi + // Split, shift and add a.lo * b.hi + "LSRS r4,r3,#16 \n\t" // r4 := (a.lo * b.hi).hi + "LSLS r3,r3,#16 \n\t" // r3 := (a.lo * b.hi).lo + "ADDS r0,r0,r3 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry + // Split, shift and add a.hi * b.lo + "LSRS r4,r5,#16 \n\t" // r4 := (a.hi * b.lo).hi + "LSLS r5,r5,#16 \n\t" // r5 := (a.hi * b.lo).lo + "ADDS r0,r0,r5 \n\t" // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo + "ADCS r1,r4 \n\t" // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries + // Finally add r[] + "LDMIA r2!,{r3,r4,r5} \n\t" + "ADDS r3,r3,r0 \n\t" + "ADCS r4,r1 \n\t" + "MOVS r0,#0 \n\t" + "ADCS r5,r0 \n\t" + "SUBS r2,#12 \n\t" + "STMIA r2!,{r3,r4,r5} \n\t" + ".syntax divided \n\t" + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "r4", "r5", "ip", "cc", "memory" +#else + "UMULL r3,ip,r0,r1 \n\t" // pre-ARMv6 requires Rd[Lo|Hi] != Rn + "LDMIA r2,{r0,r1} \n\t" + "ADDS r0,r0,r3 \n\t" + "LDR r3,[r2,#8] \n\t" + "ADCS r1,r1,ip \n\t" + "ADC r3,r3,#0 \n\t" + "STMIA r2!,{r0,r1,r3} \n\t" + : "+r"(r0), "+r"(r1), "+r"(r2) + : + : "r3", "ip", "cc", "memory" +#endif + ); +} +#else +static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { - uECC_word_t carry = uECC_vli_add(result, left, right, num_words); - if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { - /* result > mod (result = mod + remainder), so subtract mod to get + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0]; + r01 += p; + r[2] += (r01 < p); + r[1] = r01 >> uECC_WORD_BITS; + r[0] = (uECC_word_t)r01; +} +#endif +/* State for implementing random delays in uECC_vli_mult_rnd(). + * + * The state is initialized by randomizing delays and setting i = 0. + * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i. + * + * Randomized vli multiplication is used only for point operations + * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication + * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to + * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(), + * indirectly through uECC_vli_modMult_rnd(). + * + * Considering this, in order to minimize the number of calls to the RNG + * (which impact performance) while keeping the size of the structure low, + * make room for 14 randomized vli mults, which corresponds to one step in the + * scalar multiplication routine. + */ +typedef struct { + uint8_t i; + uint8_t delays[14]; +} ecc_wait_state_t; +/* + * Reset wait_state so that it's ready to be used. + */ +void ecc_wait_state_reset(ecc_wait_state_t *ws) +{ + if (ws == NULL) + return; + ws->i = 0; + mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays)); +} +/* Computes result = left * right. Result must be 2 * num_words long. + * + * As a counter-measure against horizontal attacks, add noise by performing + * a random number of extra computations performing random additional accesses + * to limbs of the input. + * + * Each of the two actual computation loops is surrounded by two + * similar-looking waiting loops, to make the beginning and end of the actual + * computation harder to spot. + * + * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That + * makes an average of 6 extra calls. Compared to the main computation which + * makes 64 such calls, this represents an average performance degradation of + * less than 10%. + * + * Compared to the original uECC_vli_mult(), loose the num_words argument as we + * know it's always 8. This saves a bit of code size and execution speed. + */ +static void uECC_vli_mult_rnd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + ecc_wait_state_t *s) +{ + uECC_word_t r[3] = { 0, 0, 0 }; + wordcount_t i, k; + const uint8_t num_words = NUM_ECC_WORDS; + /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ + uint8_t delays = s ? s->delays[s->i++] : 0; + uECC_word_t rr[3] = { 0, 0, 0 }; + volatile uECC_word_t rdummy; + /* Mimic start of next loop: k in [0, 3] */ + k = 0 + (delays & 0x03); + delays >>= 2; + /* k = 0 -> i in [1, 0] -> 0 extra muladd; + * k = 3 -> i in [1, 3] -> 3 extra muladd */ + for (i = 1; i <= k; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], r); + } + result[k] = r[0]; + r[0] = r[1]; + r[1] = r[2]; + r[2] = 0; + } + /* Mimic end of previous loop: k in [4, 7] */ + k = 4 + (delays & 0x03); + delays >>= 2; + /* k = 4 -> i in [5, 4] -> 0 extra muladd; + * k = 7 -> i in [5, 7] -> 3 extra muladd */ + for (i = 5; i <= k; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + /* Mimic start of next loop: k in [8, 11] */ + k = 11 - (delays & 0x03); + delays >>= 2; + /* k = 8 -> i in [5, 7] -> 3 extra muladd; + * k = 11 -> i in [8, 7] -> 0 extra muladd */ + for (i = (k + 5) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + for (k = num_words; k < num_words * 2 - 1; ++k) { + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], r); + } + result[k] = r[0]; + r[0] = r[1]; + r[1] = r[2]; + r[2] = 0; + } + result[num_words * 2 - 1] = r[0]; + /* Mimic end of previous loop: k in [12, 15] */ + k = 15 - (delays & 0x03); + delays >>= 2; + /* k = 12 -> i in [5, 7] -> 3 extra muladd; + * k = 15 -> i in [8, 7] -> 0 extra muladd */ + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + /* avoid warning that rdummy is set but not used */ + (void)rdummy; +} +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) +{ + uECC_word_t carry = uECC_vli_add(result, left, right); + if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ - uECC_vli_sub(result, result, mod, num_words); - } + uECC_vli_sub(result, result, mod); + } } - -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); - if (l_borrow) { - /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + uECC_word_t l_borrow = uECC_vli_sub(result, left, right); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, * we can get the correct result from result + mod (with overflow). */ - uECC_vli_add(result, result, mod, num_words); - } + uECC_vli_add(result, result, mod); + } } - /* Computes result = product % mod, where product is 2N words long. */ /* Currently only designed to work for curve_p or curve_n. */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words) +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, const uECC_word_t *mod) { - uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; - uECC_word_t tmp[2 * NUM_ECC_WORDS]; - uECC_word_t *v[2] = {tmp, product}; - uECC_word_t index; - - /* Shift mod so its highest set bit is at the maximum position. */ - bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - - uECC_vli_numBits(mod, num_words); - wordcount_t word_shift = shift / uECC_WORD_BITS; - wordcount_t bit_shift = shift % uECC_WORD_BITS; - uECC_word_t carry = 0; - uECC_vli_clear(mod_multiple, word_shift); - if (bit_shift > 0) { - for(index = 0; index < (uECC_word_t)num_words; ++index) { - mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; - carry = mod[index] >> (uECC_WORD_BITS - bit_shift); - } - } else { - uECC_vli_set(mod_multiple + word_shift, mod, num_words); - } - - for (index = 1; shift >= 0; --shift) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words * 2; ++i) { - uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; - if (diff != v[index][i]) { - borrow = (diff > v[index][i]); - } - v[1 - index][i] = diff; - } - /* Swap the index if there was no borrow */ - index = !(index ^ borrow); - uECC_vli_rshift1(mod_multiple, num_words); - mod_multiple[num_words - 1] |= mod_multiple[num_words] << - (uECC_WORD_BITS - 1); - uECC_vli_rshift1(mod_multiple + num_words, num_words); - } - uECC_vli_set(result, v[index], num_words); + uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; + uECC_word_t tmp[2 * NUM_ECC_WORDS]; + uECC_word_t *v[2] = { tmp, product }; + uECC_word_t index; + const wordcount_t num_words = NUM_ECC_WORDS; + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple); + if (bit_shift > 0) { + for (index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod); + } + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + /* Swap the index if there was no borrow */ + index = !(index ^ borrow); + uECC_vli_rshift1(mod_multiple); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words); + } + uECC_vli_set(result, v[index]); } - -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, const uECC_word_t *mod, - wordcount_t num_words) +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, num_words); - uECC_vli_mmod(result, product, mod, num_words); + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult_rnd(product, left, right, NULL); + uECC_vli_mmod(result, product, mod); } - -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve) +static void uECC_vli_modMult_rnd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + ecc_wait_state_t *s) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, curve->num_words); - - curve->mmod_fast(result, product); + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult_rnd(product, left, right, s); + vli_mmod_fast_secp256r1(result, product); } - -static void uECC_vli_modSquare_fast(uECC_word_t *result, - const uECC_word_t *left, - uECC_Curve curve) +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) { - uECC_vli_modMult_fast(result, left, left, curve); + uECC_vli_modMult_rnd(result, left, right, NULL); } - - #define EVEN(vli) (!(vli[0] & 1)) - -static void vli_modInv_update(uECC_word_t *uv, - const uECC_word_t *mod, - wordcount_t num_words) +static void vli_modInv_update(uECC_word_t *uv, const uECC_word_t *mod) { - - uECC_word_t carry = 0; - - if (!EVEN(uv)) { - carry = uECC_vli_add(uv, uv, mod, num_words); - } - uECC_vli_rshift1(uv, num_words); - if (carry) { - uv[num_words - 1] |= HIGH_BIT_SET; - } + uECC_word_t carry = 0; + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod); + } + uECC_vli_rshift1(uv); + if (carry) { + uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET; + } } - -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words) +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, const uECC_word_t *mod) { - uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; - uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; - cmpresult_t cmpResult; - - if (uECC_vli_isZero(input, num_words)) { - uECC_vli_clear(result, num_words); - return; - } - - uECC_vli_set(a, input, num_words); - uECC_vli_set(b, mod, num_words); - uECC_vli_clear(u, num_words); - u[0] = 1; - uECC_vli_clear(v, num_words); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { - if (EVEN(a)) { - uECC_vli_rshift1(a, num_words); - vli_modInv_update(u, mod, num_words); - } else if (EVEN(b)) { - uECC_vli_rshift1(b, num_words); - vli_modInv_update(v, mod, num_words); - } else if (cmpResult > 0) { - uECC_vli_sub(a, a, b, num_words); - uECC_vli_rshift1(a, num_words); - if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { - uECC_vli_add(u, u, mod, num_words); - } - uECC_vli_sub(u, u, v, num_words); - vli_modInv_update(u, mod, num_words); - } else { - uECC_vli_sub(b, b, a, num_words); - uECC_vli_rshift1(b, num_words); - if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { - uECC_vli_add(v, v, mod, num_words); - } - uECC_vli_sub(v, v, u, num_words); - vli_modInv_update(v, mod, num_words); - } - } - uECC_vli_set(result, u, num_words); + uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; + uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; + cmpresult_t cmpResult; + if (uECC_vli_isZero(input)) { + uECC_vli_clear(result); + return; + } + uECC_vli_set(a, input); + uECC_vli_set(b, mod); + uECC_vli_clear(u); + u[0] = 1; + uECC_vli_clear(v); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a); + vli_modInv_update(u, mod); + } else if (EVEN(b)) { + uECC_vli_rshift1(b); + vli_modInv_update(v, mod); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b); + uECC_vli_rshift1(a); + if (uECC_vli_cmp_unsafe(u, v) < 0) { + uECC_vli_add(u, u, mod); + } + uECC_vli_sub(u, u, v); + vli_modInv_update(u, mod); + } else { + uECC_vli_sub(b, b, a); + uECC_vli_rshift1(b); + if (uECC_vli_cmp_unsafe(v, u) < 0) { + uECC_vli_add(v, v, mod); + } + uECC_vli_sub(v, v, u); + vli_modInv_update(v, mod); + } + } + uECC_vli_set(result, u); } - /* ------ Point operations ------ */ - -void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * Z1, uECC_Curve curve) +void double_jacobian_default(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *Z1) { - /* t1 = X, t2 = Y, t3 = Z */ - uECC_word_t t4[NUM_ECC_WORDS]; - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - if (uECC_vli_isZero(Z1, num_words)) { - return; - } - - uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ - uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ - uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ - uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ - uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ - - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ - uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ - uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ - uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ - - uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ - if (uECC_vli_testBit(X1, 0)) { - uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); - uECC_vli_rshift1(X1, num_words); - X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); - } else { - uECC_vli_rshift1(X1, num_words); - } - - /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ - uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ - /* t4 = B * (A - x3) - y1^4 = y3: */ - uECC_vli_modSub(t4, X1, t4, curve->p, num_words); - - uECC_vli_set(X1, Z1, num_words); - uECC_vli_set(Z1, Y1, num_words); - uECC_vli_set(Y1, t4, num_words); + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[NUM_ECC_WORDS]; + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + if (uECC_vli_isZero(Z1)) { + return; + } + uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */ + uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ + uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ + uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ + uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p); + uECC_vli_rshift1(X1); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1); + } + /* t1 = 3/2*(x1^2 - z1^4) = B */ + uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ + /* t4 = B * (A - x3) - y1^4 = y3: */ + uECC_vli_modSub(t4, X1, t4, curve_p); + uECC_vli_set(X1, Z1); + uECC_vli_set(Z1, Y1); + uECC_vli_set(Y1, t4); } - -void x_side_default(uECC_word_t *result, - const uECC_word_t *x, - uECC_Curve curve) +/* + * @brief Computes x^3 + ax + b. result must not overlap x. + * @param result OUT -- x^3 + ax + b + * @param x IN -- value of x + * @param curve IN -- elliptic curve + */ +static void x_side_default(uECC_word_t *result, const uECC_word_t *x) { - uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ - wordcount_t num_words = curve->num_words; - - uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ - uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ - uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ - /* r = x^3 - 3x + b: */ - uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); + uECC_word_t _3[NUM_ECC_WORDS] = { 3 }; /* -a = 3 */ + uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ + /* r = x^3 - 3x + b: */ + uECC_vli_modAdd(result, result, curve_b, curve_p); } - -uECC_Curve uECC_secp256r1(void) +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product) { - return &curve_secp256r1; + unsigned int tmp[NUM_ECC_WORDS]; + int carry; + /* t */ + uECC_vli_set(result, product); + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp); + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp); + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp); + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp); + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp); + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp); + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_p); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_p, result) != 1) { + carry -= uECC_vli_sub(result, result, curve_p); + } + } } - -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) +uECC_word_t EccPoint_isZero(const uECC_word_t *point) { - unsigned int tmp[NUM_ECC_WORDS]; - int carry; - - /* t */ - uECC_vli_set(result, product, NUM_ECC_WORDS); - - /* s1 */ - tmp[0] = tmp[1] = tmp[2] = 0; - tmp[3] = product[11]; - tmp[4] = product[12]; - tmp[5] = product[13]; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s2 */ - tmp[3] = product[12]; - tmp[4] = product[13]; - tmp[5] = product[14]; - tmp[6] = product[15]; - tmp[7] = 0; - carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s3 */ - tmp[0] = product[8]; - tmp[1] = product[9]; - tmp[2] = product[10]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* s4 */ - tmp[0] = product[9]; - tmp[1] = product[10]; - tmp[2] = product[11]; - tmp[3] = product[13]; - tmp[4] = product[14]; - tmp[5] = product[15]; - tmp[6] = product[13]; - tmp[7] = product[8]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); - - /* d1 */ - tmp[0] = product[11]; - tmp[1] = product[12]; - tmp[2] = product[13]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[8]; - tmp[7] = product[10]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d2 */ - tmp[0] = product[12]; - tmp[1] = product[13]; - tmp[2] = product[14]; - tmp[3] = product[15]; - tmp[4] = tmp[5] = 0; - tmp[6] = product[9]; - tmp[7] = product[11]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d3 */ - tmp[0] = product[13]; - tmp[1] = product[14]; - tmp[2] = product[15]; - tmp[3] = product[8]; - tmp[4] = product[9]; - tmp[5] = product[10]; - tmp[6] = 0; - tmp[7] = product[12]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - /* d4 */ - tmp[0] = product[14]; - tmp[1] = product[15]; - tmp[2] = 0; - tmp[3] = product[9]; - tmp[4] = product[10]; - tmp[5] = product[11]; - tmp[6] = 0; - tmp[7] = product[13]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); - - if (carry < 0) { - do { - carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS); - } - while (carry < 0); - } else { - while (carry || - uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { - carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); - } - } + return uECC_vli_isZero(point); } - -uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) +void apply_z(uECC_word_t *X1, uECC_word_t *Y1, const uECC_word_t *const Z) { - return uECC_vli_isZero(point, curve->num_words * 2); + uECC_word_t t1[NUM_ECC_WORDS]; + uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */ } - -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve) +/* P = (x1, y1) => 2P, (x2, y2) => P' */ +static void XYcZ_initial_double(uECC_word_t *X1, + uECC_word_t *Y1, + uECC_word_t *X2, + uECC_word_t *Y2, + const uECC_word_t *const initial_Z) { - uECC_word_t t1[NUM_ECC_WORDS]; - - uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ - uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ - uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ - uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ + uECC_word_t z[NUM_ECC_WORDS]; + if (initial_Z) { + uECC_vli_set(z, initial_Z); + } else { + uECC_vli_clear(z); + z[0] = 1; + } + uECC_vli_set(X2, X1); + uECC_vli_set(Y2, Y1); + apply_z(X1, Y1, z); + double_jacobian_default(X1, Y1, z); + apply_z(X2, Y2, z); } - -/* P = (x1, y1) => 2P, (x2, y2) => P' */ -static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - const uECC_word_t * const initial_Z, - uECC_Curve curve) -{ - uECC_word_t z[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - if (initial_Z) { - uECC_vli_set(z, initial_Z, num_words); - } else { - uECC_vli_clear(z, num_words); - z[0] = 1; - } - - uECC_vli_set(X2, X1, num_words); - uECC_vli_set(Y2, Y1, num_words); - - apply_z(X1, Y1, z, curve); - curve->double_jacobian(X1, Y1, z, curve); - apply_z(X2, Y2, z, curve); +static void XYcZ_add_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2, ecc_wait_state_t *s) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ + uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ + uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */ + uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */ + uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */ + uECC_vli_set(X2, t5); } - -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) +void XYcZ_add(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ - - uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ - - uECC_vli_set(X2, t5, num_words); + XYcZ_add_rnd(X1, Y1, X2, Y2, NULL); } - /* Input P = (x1, y1, Z), Q = (x2, y2, Z) Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) or P => P - Q, Q => P + Q */ -static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) -{ - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - uECC_word_t t6[NUM_ECC_WORDS]; - uECC_word_t t7[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ - uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - - uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ - uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ - uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ - uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ - - uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ - /* t4 = (y2 - y1)*(B - x3) - E = y3: */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); - - uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ - uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ - uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ - uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ - /* t2 = (y2+y1)*(x3' - B) - E = y3': */ - uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); - - uECC_vli_set(X1, t7, num_words); +static void XYcZ_addC_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2, ecc_wait_state_t *s) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + uECC_word_t t6[NUM_ECC_WORDS]; + uECC_word_t t7[NUM_ECC_WORDS]; + uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ + uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */ + uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */ + uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */ + uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */ + uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ + /* t4 = (y2 - y1)*(B - x3) - E = y3: */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); + uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */ + uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ + /* t2 = (y2+y1)*(x3' - B) - E = y3': */ + uECC_vli_modSub(Y1, t6, Y1, curve_p); + uECC_vli_set(X1, t7); } - -void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, - const uECC_word_t * scalar, - const uECC_word_t * initial_Z, - bitcount_t num_bits, uECC_Curve curve) -{ - /* R0 and R1 */ - uECC_word_t Rx[2][NUM_ECC_WORDS]; - uECC_word_t Ry[2][NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - bitcount_t i; - uECC_word_t nb; - wordcount_t num_words = curve->num_words; - - uECC_vli_set(Rx[1], point, num_words); - uECC_vli_set(Ry[1], point + num_words, num_words); - - XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); - - for (i = num_bits - 2; i > 0; --i) { - nb = !uECC_vli_testBit(scalar, i); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); - } - - nb = !uECC_vli_testBit(scalar, 0); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); - - /* Find final 1/Z value. */ - uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ - uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ - uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ - uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ - /* yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, point + num_words, curve); - /* Xb * yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); - /* End 1/Z calculation */ - - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); - apply_z(Rx[0], Ry[0], z, curve); - - uECC_vli_set(result, Rx[0], num_words); - uECC_vli_set(result + num_words, Ry[0], num_words); +static void EccPoint_mult(uECC_word_t *result, + const uECC_word_t *point, + const uECC_word_t *scalar, + const uECC_word_t *initial_Z) +{ + /* R0 and R1 */ + uECC_word_t Rx[2][NUM_ECC_WORDS]; + uECC_word_t Ry[2][NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + bitcount_t i; + uECC_word_t nb; + const wordcount_t num_words = NUM_ECC_WORDS; + const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */ + ecc_wait_state_t wait_state; + ecc_wait_state_t *const ws = g_rng_function ? &wait_state : NULL; + uECC_vli_set(Rx[1], point); + uECC_vli_set(Ry[1], point + num_words); + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z); + for (i = num_bits - 2; i > 0; --i) { + ecc_wait_state_reset(ws); + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); + } + ecc_wait_state_reset(ws); + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words); + /* Xb * yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, Rx[1 - nb]); + /* End 1/Z calculation */ + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); + apply_z(Rx[0], Ry[0], z); + uECC_vli_set(result, Rx[0]); + uECC_vli_set(result + num_words, Ry[0]); } - -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve) +static uECC_word_t regularize_k(const uECC_word_t *const k, uECC_word_t *k0, uECC_word_t *k1) { - - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - - bitcount_t num_n_bits = curve->num_n_bits; - - uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || - (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && - uECC_vli_testBit(k0, num_n_bits)); - - uECC_vli_add(k1, k0, curve->n, num_n_words); - - return carry; + wordcount_t num_n_words = NUM_ECC_WORDS; + bitcount_t num_n_bits = NUM_ECC_BITS; + /* With our constant NUM_ECC_BITS and NUM_ECC_WORDS the + * check (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) always would have "false" result (256 < 256), + * therefore Coverity warning may be detected. Removing of this line without changing the entire check will cause to + * array overrun. + * The entire check is not changed on purpose to be aligned with original tinycrypt + * implementation and to allow upstreaming to other curves if required. + * Coverity specific annotation may be added to silence warning if exists. + */ + uECC_word_t carry = + uECC_vli_add(k0, k, curve_n) + || (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && uECC_vli_testBit(k0, num_n_bits)); + uECC_vli_add(k1, k0, curve_n); + return carry; } - -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, - uECC_word_t *private_key, - uECC_Curve curve) +int EccPoint_mult_safer(uECC_word_t *result, const uECC_word_t *point, const uECC_word_t *scalar) { - - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - uECC_word_t *p2[2] = {tmp1, tmp2}; - uECC_word_t carry; - - /* Regularize the bitcount for the private key so that attackers cannot - * use a side channel attack to learn the number of leading zeros. */ - carry = regularize_k(private_key, tmp1, tmp2, curve); - - EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); - - if (EccPoint_isZero(result, curve)) { - return 0; - } - return 1; + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t *k2[2] = { tmp, s }; + wordcount_t num_words = NUM_ECC_WORDS; + uECC_word_t carry; + uECC_word_t *initial_Z = 0; + int r = UECC_FAULT_DETECTED; + volatile int problem; + /* Protect against faults modifying curve paremeters in flash */ + problem = -1; + problem = uECC_check_curve_integrity(); + if (problem != 0) { + return UECC_FAULT_DETECTED; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + return UECC_FAULT_DETECTED; + } + /* Protects against invalid curve attacks */ + problem = -1; + problem = uECC_valid_point(point); + if (problem != 0) { + /* invalid input, can happen without fault */ + return UECC_FAILURE; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + /* failure on second check means fault, though */ + return UECC_FAULT_DETECTED; + } + /* Regularize the bitcount for the private key so that attackers cannot use a + * side channel attack to learn the number of leading zeros. */ + carry = regularize_k(scalar, tmp, s); + /* If an RNG function was specified, get a random initial Z value to + * protect against side-channel attacks such as Template SPA */ + if (g_rng_function) { + if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) { + r = UECC_FAILURE; + goto clear_and_out; + } + initial_Z = k2[carry]; + } + EccPoint_mult(result, point, k2[!carry], initial_Z); + /* Protect against fault injections that would make the resulting + * point not lie on the intended curve */ + problem = -1; + problem = uECC_valid_point(result); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + /* Protect against faults modifying curve paremeters in flash */ + problem = -1; + problem = uECC_check_curve_integrity(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + r = UECC_SUCCESS; +clear_and_out: + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_zeroize(k2, sizeof(k2)); + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + mbedtls_platform_zeroize(s, sizeof(s)); + return r; +} +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key) +{ + return EccPoint_mult_safer(result, curve_G, private_key); } - /* Converts an integer in uECC native format to big-endian bytes. */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, - const unsigned int *native) +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const unsigned int *native) { - wordcount_t i; - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); - } + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } } - /* Converts big-endian bytes to an integer in uECC native format. */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, - int num_bytes) +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, int num_bytes) { - wordcount_t i; - uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - native[b / uECC_WORD_SIZE] |= - (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); - } + wordcount_t i; + uECC_vli_clear(native); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } } - -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, - wordcount_t num_words) +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, wordcount_t num_words) { - uECC_word_t mask = (uECC_word_t)-1; - uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top, num_words); - - if (!g_rng_function) { - return 0; - } - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { - return 0; - } - random[num_words - 1] &= - mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random, num_words) && - uECC_vli_cmp(top, random, num_words) == 1) { - return 1; - } - } - return 0; + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top); + if (!g_rng_function) { + return UECC_FAILURE; + } + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) { + return UECC_FAILURE; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random) && uECC_vli_cmp(top, random) == 1) { + return UECC_SUCCESS; + } + } + return UECC_FAILURE; } - - -int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) +int uECC_valid_point(const uECC_word_t *point) { - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - /* The point at infinity is invalid. */ - if (EccPoint_isZero(point, curve)) { - return -1; - } - - /* x and y must be smaller than p. */ - if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || - uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { - return -2; - } - - uECC_vli_modSquare_fast(tmp1, point + num_words, curve); - curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ - - /* Make sure that y^2 == x^3 + ax + b */ - if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) - return -3; - - return 0; + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + volatile uECC_word_t diff = 0xffffffff; + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point)) { + return -1; + } + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve_p, point) != 1 || uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) { + return -2; + } + uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words); + x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */ + /* Make sure that y^2 == x^3 + ax + b */ + diff = uECC_vli_equal(tmp1, tmp2); + if (diff == 0) { + mbedtls_platform_random_delay(); + if (diff == 0) { + return 0; + } + } + return -3; } - -int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) +int uECC_valid_public_key(const uint8_t *public_key) { - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); - uECC_vli_bytesToNative( - _public + curve->num_words, - public_key + curve->num_bytes, - curve->num_bytes); - - if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { - return -4; - } - - return uECC_valid_point(_public, curve); + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); + uECC_vli_bytesToNative(_public + NUM_ECC_WORDS, public_key + NUM_ECC_BYTES, NUM_ECC_BYTES); + if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) { + return -4; + } + return uECC_valid_point(_public); } - -int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, - uECC_Curve curve) +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key) { - - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - uECC_vli_bytesToNative( - _private, - private_key, - BITS_TO_BYTES(curve->num_n_bits)); - - /* Make sure the private key is in the range [1, n-1]. */ - if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { - return 0; - } - - if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { - return 0; - } - - /* Compute public key. */ - if (!EccPoint_compute_public_key(_public, _private, curve)) { - return 0; - } - - uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); - uECC_vli_nativeToBytes( - public_key + - curve->num_bytes, curve->num_bytes, _public + curve->num_words); - return 1; + int ret = UECC_FAULT_DETECTED; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private)) { + return UECC_FAILURE; + } + if (uECC_vli_cmp(curve_n, _private) != 1) { + return UECC_FAILURE; + } + /* Compute public key. */ + ret = EccPoint_compute_public_key(_public, _private); + if (ret != UECC_SUCCESS) { + return ret; + } + uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); + uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); + return ret; } - - - +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index 5624c96446..c765d052a3 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -1,16 +1,19 @@ /* ec_dh.c - TinyCrypt implementation of EC-DH */ - -/* +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ +/* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -24,23 +27,22 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -54,139 +56,99 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#if defined(SL_MBEDTLS_USE_TINYCRYPT) #include #include -#include +#include #include - -int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, - unsigned int *d, uECC_Curve curve) +#include "mbedtls/platform_util.h" +int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, unsigned int *d) { - - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - - /* This function is designed for test purposes-only (such as validating NIST + int ret = UECC_FAULT_DETECTED; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + /* This function is designed for test purposes-only (such as validating NIST * test vectors) as it uses a provided value for d instead of generating * it uniformly at random. */ - memcpy (_private, d, NUM_ECC_BYTES); - - /* Computing public-key from private: */ - if (EccPoint_compute_public_key(_public, _private, curve)) { - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, - BITS_TO_BYTES(curve->num_n_bits), - _private); - uECC_vli_nativeToBytes(public_key, - curve->num_bytes, - _public); - uECC_vli_nativeToBytes(public_key + curve->num_bytes, - curve->num_bytes, - _public + curve->num_words); - - /* erasing temporary buffer used to store secret: */ - _set_secure(_private, 0, NUM_ECC_BYTES); - - return 1; - } - return 0; + if (mbedtls_platform_memcpy(_private, d, NUM_ECC_BYTES) != _private) { + goto exit; + } + /* Computing public-key from private: */ + ret = EccPoint_compute_public_key(_public, _private); + if (ret != UECC_SUCCESS) { + goto exit; + } + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(NUM_ECC_BITS), _private); + uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); + uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); +exit: + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); + return ret; } - -int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) +int uECC_make_key(uint8_t *public_key, uint8_t *private_key) { - - uECC_word_t _random[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t tries; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _private uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - !rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) { - return 0; - } - - /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ - uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); - - /* Computing public-key from private: */ - if (EccPoint_compute_public_key(_public, _private, curve)) { - - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, - BITS_TO_BYTES(curve->num_n_bits), - _private); - uECC_vli_nativeToBytes(public_key, - curve->num_bytes, - _public); - uECC_vli_nativeToBytes(public_key + curve->num_bytes, - curve->num_bytes, - _public + curve->num_words); - - /* erasing temporary buffer that stored secret: */ - _set_secure(_private, 0, NUM_ECC_BYTES); - - return 1; - } - } - return 0; + int ret = UECC_FAULT_DETECTED; + uECC_word_t _random[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t tries; + volatile uint8_t *public_key_dup = public_key; + volatile uint8_t *private_key_dup = private_key; + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _private uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function + || rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { + return UECC_FAILURE; + } + /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ + uECC_vli_mmod(_private, _random, curve_n); + /* Computing public-key from private: */ + ret = EccPoint_compute_public_key(_public, _private); + /* don't try again if a fault was detected */ + if (ret == UECC_FAULT_DETECTED) { + return ret; + } + if (ret == UECC_SUCCESS) { + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(NUM_ECC_BITS), _private); + uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); + uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); + /* erasing temporary buffer that stored secret: */ + mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); + if (private_key == private_key_dup && public_key == public_key_dup) { + return UECC_SUCCESS; + } + /* Erase key in case of FI */ + mbedtls_platform_memset(public_key, 0, 2 * NUM_ECC_BYTES); + return UECC_FAULT_DETECTED; + } + } + return UECC_FAILURE; } - -int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, - uint8_t *secret, uECC_Curve curve) +int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uint8_t *secret) { - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t *p2[2] = {_private, tmp}; - uECC_word_t *initial_Z = 0; - uECC_word_t carry; - wordcount_t num_words = curve->num_words; - wordcount_t num_bytes = curve->num_bytes; - int r; - - /* Converting buffers to correct bit order: */ - uECC_vli_bytesToNative(_private, - private_key, - BITS_TO_BYTES(curve->num_n_bits)); - uECC_vli_bytesToNative(_public, - public_key, - num_bytes); - uECC_vli_bytesToNative(_public + num_words, - public_key + num_bytes, - num_bytes); - - /* Regularize the bitcount for the private key so that attackers cannot use a - * side channel attack to learn the number of leading zeros. */ - carry = regularize_k(_private, _private, tmp, curve); - - /* If an RNG function was specified, try to get a random initial Z value to - * improve protection against side-channel attacks. */ - if (uECC_get_rng()) { - if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { - r = 0; - goto clear_and_out; - } - initial_Z = p2[carry]; - } - - EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, - curve); - - uECC_vli_nativeToBytes(secret, num_bytes, _public); - r = !EccPoint_isZero(_public, curve); - -clear_and_out: - /* erasing temporary buffer used to store secret: */ - _set_secure(p2, 0, sizeof(p2)); - _set_secure(tmp, 0, sizeof(tmp)); - _set_secure(_private, 0, sizeof(_private)); - - return r; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + wordcount_t num_bytes = NUM_ECC_BYTES; + int r = UECC_FAULT_DETECTED; + /* Converting buffers to correct bit order: */ + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); + uECC_vli_bytesToNative(_public, public_key, num_bytes); + uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes); + r = EccPoint_mult_safer(_public, _public, _private); + uECC_vli_nativeToBytes(secret, num_bytes, _public); + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_zeroize(_private, sizeof(_private)); + + return UECC_FAULT_DETECTED; } +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/ecc_dsa.c b/matter/mbedtls/tinycrypt/src/ecc_dsa.c index 06f077b478..dbaa4e62e6 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dsa.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dsa.c @@ -1,15 +1,18 @@ /* ec_dsa.c - TinyCrypt implementation of EC-DSA */ - +/* + * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: BSD-3-Clause + */ /* Copyright (c) 2014, Kenneth MacKay * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -22,23 +25,22 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE.*/ - /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * - Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -52,239 +54,213 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - -#include +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#if defined(SL_MBEDTLS_USE_TINYCRYPT) #include #include - - -static void bits2int(uECC_word_t *native, const uint8_t *bits, - unsigned bits_size, uECC_Curve curve) +#include "mbedtls/platform_util.h" +static void bits2int(uECC_word_t *native, const uint8_t *bits, unsigned bits_size) { - unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); - unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); - int shift; - uECC_word_t carry; - uECC_word_t *ptr; - - if (bits_size > num_n_bytes) { - bits_size = num_n_bytes; - } - - uECC_vli_clear(native, num_n_words); - uECC_vli_bytesToNative(native, bits, bits_size); - if (bits_size * 8 <= (unsigned)curve->num_n_bits) { - return; - } - shift = bits_size * 8 - curve->num_n_bits; - carry = 0; - ptr = native + num_n_words; - while (ptr-- > native) { - uECC_word_t temp = *ptr; - *ptr = (temp >> shift) | carry; - carry = temp << (uECC_WORD_BITS - shift); - } - - /* Reduce mod curve_n */ - if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { - uECC_vli_sub(native, native, curve->n, num_n_words); - } + unsigned num_n_bytes = BITS_TO_BYTES(NUM_ECC_BITS); + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + uECC_vli_clear(native); + uECC_vli_bytesToNative(native, bits, bits_size); } - -int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uECC_word_t *k, uint8_t *signature, - uECC_Curve curve) +int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uECC_word_t *k, + uint8_t *signature) { - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t *k2[2] = {tmp, s}; - uECC_word_t p[NUM_ECC_WORDS * 2]; - uECC_word_t carry; - wordcount_t num_words = curve->num_words; - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - bitcount_t num_n_bits = curve->num_n_bits; - - /* Make sure 0 < k < curve_n */ - if (uECC_vli_isZero(k, num_words) || - uECC_vli_cmp(curve->n, k, num_n_words) != 1) { - return 0; - } - - carry = regularize_k(k, tmp, s, curve); - EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve); - if (uECC_vli_isZero(p, num_words)) { - return 0; - } - - /* If an RNG function was specified, get a random number + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t p[NUM_ECC_WORDS * 2]; + wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); + int r = UECC_FAILURE; + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k) || uECC_vli_cmp(curve_n, k) != 1) { + return UECC_FAILURE; + } + r = EccPoint_mult_safer(p, curve_G, k); + if (r != UECC_SUCCESS) { + return r; + } + /* If an RNG function was specified, get a random number to prevent side channel analysis of k. */ - if (!uECC_get_rng()) { - uECC_vli_clear(tmp, num_n_words); - tmp[0] = 1; - } - else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { - return 0; - } - - /* Prevent side channel analysis of uECC_vli_modInv() to determine + if (!uECC_get_rng()) { + uECC_vli_clear(tmp); + tmp[0] = 1; + } else if (uECC_generate_random_int(tmp, curve_n, num_n_words) != UECC_SUCCESS) { + return UECC_FAILURE; + } + /* Prevent side channel analysis of uECC_vli_modInv() to determine bits of k / the private key by premultiplying by a random number */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ - uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ - - uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ - - /* tmp = d: */ - uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); - - s[num_n_words - 1] = 0; - uECC_vli_set(s, p, num_words); - uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ - - bits2int(tmp, message_hash, hash_size, curve); - uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ - uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ - if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { - return 0; - } - - uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); - return 1; + uECC_vli_modMult(k, k, tmp, curve_n); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve_n); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve_n); /* k = 1 / k */ + uECC_vli_nativeToBytes(signature, NUM_ECC_BYTES, p); /* store r */ + /* tmp = d: */ + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); + s[num_n_words - 1] = 0; + uECC_vli_set(s, p); + uECC_vli_modMult(s, tmp, s, curve_n); /* s = r*d */ + bits2int(tmp, message_hash, hash_size); + uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) { + return UECC_FAILURE; + } + uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s); + return r; } - -int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, - unsigned hash_size, uint8_t *signature, uECC_Curve curve) +int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, uint8_t *signature) { - uECC_word_t _random[2*NUM_ECC_WORDS]; - uECC_word_t k[NUM_ECC_WORDS]; - uECC_word_t tries; - - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _random uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function || - !rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) { - return 0; - } - - // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): - uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); - - if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, - curve)) { - return 1; - } - } - return 0; + int r; + uECC_word_t _random[2 * NUM_ECC_WORDS]; + uECC_word_t k[NUM_ECC_WORDS]; + uECC_word_t tries; + volatile const uint8_t *private_key_dup = private_key; + volatile const uint8_t *message_hash_dup = message_hash; + volatile unsigned hash_size_dup = hash_size; + volatile uint8_t *signature_dup = signature; + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _random uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function + || rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { + return UECC_FAILURE; + } + // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): + uECC_vli_mmod(k, _random, curve_n); + r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature); + /* don't keep trying if a fault was detected */ + if (r == UECC_FAULT_DETECTED) { + mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); + return r; + } + if (r == UECC_SUCCESS) { + if (private_key_dup != private_key || message_hash_dup != message_hash || hash_size_dup != hash_size + || signature_dup != signature) { + mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); + return UECC_FAULT_DETECTED; + } + return UECC_SUCCESS; + } + /* else keep trying */ + } + return UECC_FAILURE; } - static bitcount_t smax(bitcount_t a, bitcount_t b) { - return (a > b ? a : b); + return (a > b ? a : b); } - -int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, - unsigned hash_size, const uint8_t *signature, - uECC_Curve curve) +int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, unsigned hash_size, const uint8_t *signature) { - - uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - uECC_word_t sum[NUM_ECC_WORDS * 2]; - uECC_word_t rx[NUM_ECC_WORDS]; - uECC_word_t ry[NUM_ECC_WORDS]; - uECC_word_t tx[NUM_ECC_WORDS]; - uECC_word_t ty[NUM_ECC_WORDS]; - uECC_word_t tz[NUM_ECC_WORDS]; - const uECC_word_t *points[4]; - const uECC_word_t *point; - bitcount_t num_bits; - bitcount_t i; - - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - - rx[num_n_words - 1] = 0; - r[num_n_words - 1] = 0; - s[num_n_words - 1] = 0; - - uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); - uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes, - curve->num_bytes); - uECC_vli_bytesToNative(r, signature, curve->num_bytes); - uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); - - /* r, s must not be 0. */ - if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { - return 0; - } - - /* r, s must be < n. */ - if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || - uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { - return 0; - } - - /* Calculate u1 and u2. */ - uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ - u1[num_n_words - 1] = 0; - bits2int(u1, message_hash, hash_size, curve); - uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ - uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ - - /* Calculate sum = G + Q. */ - uECC_vli_set(sum, _public, num_words); - uECC_vli_set(sum + num_words, _public + num_words, num_words); - uECC_vli_set(tx, curve->G, num_words); - uECC_vli_set(ty, curve->G + num_words, num_words); - uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ - XYcZ_add(tx, ty, sum, sum + num_words, curve); - uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ - apply_z(sum, sum + num_words, z, curve); - - /* Use Shamir's trick to calculate u1*G + u2*Q */ - points[0] = 0; - points[1] = curve->G; - points[2] = _public; - points[3] = sum; - num_bits = smax(uECC_vli_numBits(u1, num_n_words), - uECC_vli_numBits(u2, num_n_words)); - - point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | - ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; - uECC_vli_set(rx, point, num_words); - uECC_vli_set(ry, point + num_words, num_words); - uECC_vli_clear(z, num_words); - z[0] = 1; - - for (i = num_bits - 2; i >= 0; --i) { - uECC_word_t index; - curve->double_jacobian(rx, ry, z, curve); - - index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); - point = points[index]; - if (point) { - uECC_vli_set(tx, point, num_words); - uECC_vli_set(ty, point + num_words, num_words); - apply_z(tx, ty, z, curve); - uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ - XYcZ_add(tx, ty, rx, ry, curve); - uECC_vli_modMult_fast(z, z, tz, curve); - } - } - - uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ - apply_z(rx, ry, z, curve); - - /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { - uECC_vli_sub(rx, rx, curve->n, num_n_words); - } - - /* Accept only if v == r. */ - return (int)(uECC_vli_equal(rx, r, num_words) == 0); + uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + uECC_word_t sum[NUM_ECC_WORDS * 2]; + uECC_word_t rx[NUM_ECC_WORDS]; + uECC_word_t ry[NUM_ECC_WORDS]; + uECC_word_t tx[NUM_ECC_WORDS]; + uECC_word_t ty[NUM_ECC_WORDS]; + uECC_word_t tz[NUM_ECC_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + bitcount_t flow_control; + volatile uECC_word_t diff; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + flow_control = 1; + uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); + uECC_vli_bytesToNative(_public + num_words, public_key + NUM_ECC_BYTES, NUM_ECC_BYTES); + uECC_vli_bytesToNative(r, signature, NUM_ECC_BYTES); + uECC_vli_bytesToNative(s, signature + NUM_ECC_BYTES, NUM_ECC_BYTES); + /* r, s must not be 0. */ + if (uECC_vli_isZero(r) || uECC_vli_isZero(s)) { + return UECC_FAILURE; + } + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve_n, r) != 1 || uECC_vli_cmp_unsafe(curve_n, s) != 1) { + return UECC_FAILURE; + } + flow_control++; + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve_n); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size); + uECC_vli_modMult(u1, u1, z, curve_n); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve_n); /* u2 = r/s */ + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public); + uECC_vli_set(sum + num_words, _public + num_words); + uECC_vli_set(tx, curve_G); + uECC_vli_set(ty, curve_G + num_words); + uECC_vli_modSub(z, sum, tx, curve_p); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words); + uECC_vli_modInv(z, z, curve_p); /* z = 1/z */ + apply_z(sum, sum + num_words, z); + flow_control++; + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve_G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1), uECC_vli_numBits(u2)); + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point); + uECC_vli_set(ry, point + num_words); + uECC_vli_clear(z); + z[0] = 1; + flow_control++; + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + double_jacobian_default(rx, ry, z); + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point); + uECC_vli_set(ty, point + num_words); + apply_z(tx, ty, z); + uECC_vli_modSub(tz, rx, tx, curve_p); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry); + uECC_vli_modMult_fast(z, z, tz); + } + flow_control++; + } + uECC_vli_modInv(z, z, curve_p); /* Z = 1/Z */ + apply_z(rx, ry, z); + flow_control++; + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve_n, rx) != 1) { + uECC_vli_sub(rx, rx, curve_n); + } + /* Accept only if v == r. */ + diff = uECC_vli_equal(rx, r); + if (diff == 0) { + flow_control++; + mbedtls_platform_random_delay(); + /* Re-check the condition and test if the control flow is as expected. + * 1 (base value) + num_bits - 1 (from the loop) + 5 incrementations. + */ + if (diff == 0 && flow_control == (num_bits + 5)) { + return UECC_SUCCESS; + } else { + return UECC_FAULT_DETECTED; + } + } + return UECC_FAILURE; } - +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/hmac.c b/matter/mbedtls/tinycrypt/src/hmac.c index cef5bf39b2..89878cec78 100644 --- a/matter/mbedtls/tinycrypt/src/hmac.c +++ b/matter/mbedtls/tinycrypt/src/hmac.c @@ -52,19 +52,20 @@ static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, unsigned int key_size) { - /* Input sanity check */ + + /* input sanity check: */ if (ctx == (TCHmacState_t) 0 || key == (const uint8_t *) 0 || key_size == 0) { return TC_CRYPTO_FAIL; } - const uint8_t dummy_key[TC_SHA256_BLOCK_SIZE]; + const uint8_t dummy_key[key_size]; struct tc_hmac_state_struct dummy_state; if (key_size <= TC_SHA256_BLOCK_SIZE) { /* - * The next three calls are dummy calls just to avoid + * The next three lines consist of dummy calls just to avoid * certain timing attacks. Without these dummy calls, * adversaries would be able to learn whether the key_size is * greater than TC_SHA256_BLOCK_SIZE by measuring the time diff --git a/matter/mbedtls/tinycrypt/src/hmac_prng.c b/matter/mbedtls/tinycrypt/src/hmac_prng.c index 84e7918b8c..68b5b1fafb 100644 --- a/matter/mbedtls/tinycrypt/src/hmac_prng.c +++ b/matter/mbedtls/tinycrypt/src/hmac_prng.c @@ -73,28 +73,19 @@ static const unsigned int MAX_GENS = UINT32_MAX; static const unsigned int MAX_OUT = (1 << 19); /* - * Assumes: prng != NULL + * Assumes: prng != NULL, e != NULL, len >= 0. */ -static void update(TCHmacPrng_t prng, const uint8_t *data, unsigned int datalen, const uint8_t *additional_data, unsigned int additional_datalen) +static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len) { const uint8_t separator0 = 0x00; const uint8_t separator1 = 0x01; - /* configure the new prng key into the prng's instance of hmac */ - tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - /* use current state, e and separator 0 to compute a new prng key: */ (void)tc_hmac_init(&prng->h); (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0)); - - if (data && datalen) - (void)tc_hmac_update(&prng->h, data, datalen); - if (additional_data && additional_datalen) - (void)tc_hmac_update(&prng->h, additional_data, additional_datalen); - + (void)tc_hmac_update(&prng->h, e, len); (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); @@ -103,21 +94,12 @@ static void update(TCHmacPrng_t prng, const uint8_t *data, unsigned int datalen, (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); - if (data == 0 || datalen == 0) - return; - - /* configure the new prng key into the prng's instance of hmac */ - tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - /* use current state, e and separator 1 to compute a new prng key: */ (void)tc_hmac_init(&prng->h); (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1)); - (void)tc_hmac_update(&prng->h, data, datalen); - if (additional_data && additional_datalen) - (void)tc_hmac_update(&prng->h, additional_data, additional_datalen); + (void)tc_hmac_update(&prng->h, e, len); (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); @@ -142,8 +124,10 @@ int tc_hmac_prng_init(TCHmacPrng_t prng, /* put the generator into a known state: */ _set(prng->key, 0x00, sizeof(prng->key)); _set(prng->v, 0x01, sizeof(prng->v)); + tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); + /* update assumes SOME key has been configured into HMAC */ - update(prng, personalization, plen, 0, 0); + update(prng, personalization, plen); /* force a reseed before allowing tc_hmac_prng_generate to succeed: */ prng->countdown = 0; @@ -175,12 +159,13 @@ int tc_hmac_prng_reseed(TCHmacPrng_t prng, additionallen > MAX_ALEN) { return TC_CRYPTO_FAIL; } else { - /* call update for the seed and additional_input */ - update(prng, seed, seedlen, additional_input, additionallen); + /* call update for the seed and additional_input */ + update(prng, seed, seedlen); + update(prng, additional_input, additionallen); } } else { /* call update only for the seed */ - update(prng, seed, seedlen, 0, 0); + update(prng, seed, seedlen); } /* ... and enable hmac_prng_generate */ @@ -206,9 +191,6 @@ int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) prng->countdown--; while (outlen != 0) { - /* configure the new prng key into the prng's instance of hmac */ - tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - /* operate HMAC in OFB mode to create "random" outputs */ (void)tc_hmac_init(&prng->h); (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); @@ -224,7 +206,7 @@ int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) } /* block future PRNG compromises from revealing past state */ - update(prng, 0, 0, 0, 0); + update(prng, prng->v, TC_SHA256_DIGEST_SIZE); return TC_CRYPTO_SUCCESS; } diff --git a/matter/mbedtls/tinycrypt/src/oid.c b/matter/mbedtls/tinycrypt/src/oid.c deleted file mode 100644 index 1c95b844b4..0000000000 --- a/matter/mbedtls/tinycrypt/src/oid.c +++ /dev/null @@ -1,884 +0,0 @@ -/** - * \file oid.c - * - * \brief Object Identifier (OID) database - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_OID_C) - -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/rsa.h" - -#include -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#endif - -/* - * Macro to automatically add the size of #define'd OIDs - */ -#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) -#define NULL_OID_DESCRIPTOR \ - { NULL, 0 } - -/* - * Macro to generate an internal function for oid_XXX_from_asn1() (used by - * the other functions) - */ -#define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST) \ - static const TYPE_T *oid_##NAME##_from_asn1(const mbedtls_asn1_buf *oid) { \ - const TYPE_T *p = (LIST); \ - const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *)p; \ - if (p == NULL || oid == NULL) \ - return (NULL); \ - while (cur->asn1 != NULL) { \ - if (cur->asn1_len == oid->len && \ - memcmp(cur->asn1, oid->p, oid->len) == 0) { \ - return (p); \ - } \ - p++; \ - cur = (const mbedtls_oid_descriptor_t *)p; \ - } \ - return (NULL); \ - } - -/* - * Macro to generate a function for retrieving a single attribute from the - * descriptor of an mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, \ - ATTR1) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE *ATTR1) { \ - const TYPE_T *data = oid_##TYPE_NAME##_from_asn1(oid); \ - if (data == NULL) \ - return (MBEDTLS_ERR_OID_NOT_FOUND); \ - *ATTR1 = data->descriptor.ATTR1; \ - return (0); \ - } - -/* - * Macro to generate a function for retrieving a single attribute from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE *ATTR1) { \ - const TYPE_T *data = oid_##TYPE_NAME##_from_asn1(oid); \ - if (data == NULL) \ - return (MBEDTLS_ERR_OID_NOT_FOUND); \ - *ATTR1 = data->ATTR1; \ - return (0); \ - } - -/* - * Macro to generate a function for retrieving two attributes from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE *ATTR1, \ - ATTR2_TYPE *ATTR2) { \ - const TYPE_T *data = oid_##TYPE_NAME##_from_asn1(oid); \ - if (data == NULL) \ - return (MBEDTLS_ERR_OID_NOT_FOUND); \ - *(ATTR1) = data->ATTR1; \ - *(ATTR2) = data->ATTR2; \ - return (0); \ - } - -/* - * Macro to generate a function for retrieving the OID based on a single - * attribute from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ - int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen) { \ - const TYPE_T *cur = (LIST); \ - while (cur->descriptor.asn1 != NULL) { \ - if (cur->ATTR1 == (ATTR1)) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return (0); \ - } \ - cur++; \ - } \ - return (MBEDTLS_ERR_OID_NOT_FOUND); \ - } - -/* - * Macro to generate a function for retrieving the OID based on two - * attributes from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ - int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid, \ - size_t *olen) { \ - const TYPE_T *cur = (LIST); \ - while (cur->descriptor.asn1 != NULL) { \ - if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return (0); \ - } \ - cur++; \ - } \ - return (MBEDTLS_ERR_OID_NOT_FOUND); \ - } - -/* - * For X520 attribute types - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - const char *short_name; -} oid_x520_attr_t; - -static const oid_x520_attr_t oid_x520_attr_type[] = { - { - {ADD_LEN(MBEDTLS_OID_AT_CN), "id-at-commonName", "Common Name"}, - "CN", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_COUNTRY), "id-at-countryName", "Country"}, - "C", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_LOCALITY), "id-at-locality", "Locality"}, - "L", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_STATE), "id-at-state", "State"}, - "ST", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_ORGANIZATION), "id-at-organizationName", - "Organization"}, - "O", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_ORG_UNIT), "id-at-organizationalUnitName", - "Org Unit"}, - "OU", - }, - { - {ADD_LEN(MBEDTLS_OID_PKCS9_EMAIL), "emailAddress", "E-mail address"}, - "emailAddress", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_SERIAL_NUMBER), "id-at-serialNumber", - "Serial number"}, - "serialNumber", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_POSTAL_ADDRESS), "id-at-postalAddress", - "Postal address"}, - "postalAddress", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_POSTAL_CODE), "id-at-postalCode", - "Postal code"}, - "postalCode", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_SUR_NAME), "id-at-surName", "Surname"}, - "SN", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_GIVEN_NAME), "id-at-givenName", "Given name"}, - "GN", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_INITIALS), "id-at-initials", "Initials"}, - "initials", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_GENERATION_QUALIFIER), - "id-at-generationQualifier", "Generation qualifier"}, - "generationQualifier", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_TITLE), "id-at-title", "Title"}, - "title", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_DN_QUALIFIER), "id-at-dnQualifier", - "Distinguished Name qualifier"}, - "dnQualifier", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_PSEUDONYM), "id-at-pseudonym", "Pseudonym"}, - "pseudonym", - }, - { - {ADD_LEN(MBEDTLS_OID_DOMAIN_COMPONENT), "id-domainComponent", - "Domain component"}, - "DC", - }, - { - {ADD_LEN(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER), "id-at-uniqueIdentifier", - "Unique Identifier"}, - "uniqueIdentifier", - }, - { - {NULL, 0, NULL, NULL}, - NULL, - }}; - -FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) -FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, - const char *, short_name) - -/* - * For X509 extensions - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - int ext_type; -} oid_x509_ext_t; - -static const oid_x509_ext_t oid_x509_ext[] = { - { - {ADD_LEN(MBEDTLS_OID_BASIC_CONSTRAINTS), "id-ce-basicConstraints", - "Basic Constraints"}, - MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, - }, - { - {ADD_LEN(MBEDTLS_OID_KEY_USAGE), "id-ce-keyUsage", "Key Usage"}, - MBEDTLS_OID_X509_EXT_KEY_USAGE, - }, - { - {ADD_LEN(MBEDTLS_OID_EXTENDED_KEY_USAGE), "id-ce-extKeyUsage", - "Extended Key Usage"}, - MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, - }, - { - {ADD_LEN(MBEDTLS_OID_SUBJECT_ALT_NAME), "id-ce-subjectAltName", - "Subject Alt Name"}, - MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, - }, - { - {ADD_LEN(MBEDTLS_OID_NS_CERT_TYPE), "id-netscape-certtype", - "Netscape Certificate Type"}, - MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, - }, - { - {ADD_LEN(MBEDTLS_OID_CERTIFICATE_POLICIES), "id-ce-certificatePolicies", - "Certificate Policies"}, - MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, - }, - { - {NULL, 0, NULL, NULL}, - 0, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) -FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, - ext_type) - -static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { - {ADD_LEN(MBEDTLS_OID_SERVER_AUTH), "id-kp-serverAuth", - "TLS Web Server Authentication"}, - {ADD_LEN(MBEDTLS_OID_CLIENT_AUTH), "id-kp-clientAuth", - "TLS Web Client Authentication"}, - {ADD_LEN(MBEDTLS_OID_CODE_SIGNING), "id-kp-codeSigning", "Code Signing"}, - {ADD_LEN(MBEDTLS_OID_EMAIL_PROTECTION), "id-kp-emailProtection", - "E-mail Protection"}, - {ADD_LEN(MBEDTLS_OID_TIME_STAMPING), "id-kp-timeStamping", "Time Stamping"}, - {ADD_LEN(MBEDTLS_OID_OCSP_SIGNING), "id-kp-OCSPSigning", "OCSP Signing"}, - {ADD_LEN(MBEDTLS_OID_WISUN_FAN), "id-kp-wisun-fan-device", - "Wi-SUN Alliance Field Area Network (FAN)"}, - {NULL, 0, NULL, NULL}, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, - oid_ext_key_usage) -FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, - ext_key_usage, const char *, description) - -static const mbedtls_oid_descriptor_t oid_certificate_policies[] = { - {ADD_LEN(MBEDTLS_OID_ANY_POLICY), "anyPolicy", "Any Policy"}, - {NULL, 0, NULL, NULL}, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, - oid_certificate_policies) -FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, - certificate_policies, const char *, description) - -#if defined(MBEDTLS_MD_C) -/* - * For SignatureAlgorithmIdentifier - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_pk_type_t pk_alg; -} oid_sig_alg_t; - -static const oid_sig_alg_t oid_sig_alg[] = { -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_MD2_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_MD2), "md2WithRSAEncryption", - "RSA with MD2"}, - MBEDTLS_MD_MD2, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_MD4), "md4WithRSAEncryption", - "RSA with MD4"}, - MBEDTLS_MD_MD4, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_MD5), "md5WithRSAEncryption", - "RSA with MD5"}, - MBEDTLS_MD_MD5, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_SHA1), "sha-1WithRSAEncryption", - "RSA with SHA1"}, - MBEDTLS_MD_SHA1, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_SHA224), "sha224WithRSAEncryption", - "RSA with SHA-224"}, - MBEDTLS_MD_SHA224, - MBEDTLS_PK_RSA, - }, - { - {ADD_LEN(MBEDTLS_OID_PKCS1_SHA256), "sha256WithRSAEncryption", - "RSA with SHA-256"}, - MBEDTLS_MD_SHA256, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - {ADD_LEN(MBEDTLS_OID_PKCS1_SHA384), "sha384WithRSAEncryption", - "RSA with SHA-384"}, - MBEDTLS_MD_SHA384, - MBEDTLS_PK_RSA, - }, - { - {ADD_LEN(MBEDTLS_OID_PKCS1_SHA512), "sha512WithRSAEncryption", - "RSA with SHA-512"}, - MBEDTLS_MD_SHA512, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SHA1_C) - { - {ADD_LEN(MBEDTLS_OID_RSA_SHA_OBS), "sha-1WithRSAEncryption", - "RSA with SHA1"}, - MBEDTLS_MD_SHA1, - MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) || defined(TINYCRYPT_PRIMITIVES) -#if defined(MBEDTLS_SHA1_C) - { - {ADD_LEN(MBEDTLS_OID_ECDSA_SHA1), "ecdsa-with-SHA1", "ECDSA with SHA1"}, - MBEDTLS_MD_SHA1, - MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - {ADD_LEN(MBEDTLS_OID_ECDSA_SHA224), "ecdsa-with-SHA224", - "ECDSA with SHA224"}, - MBEDTLS_MD_SHA224, - MBEDTLS_PK_ECDSA, - }, - { - {ADD_LEN(MBEDTLS_OID_ECDSA_SHA256), "ecdsa-with-SHA256", - "ECDSA with SHA256"}, - MBEDTLS_MD_SHA256, - MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - {ADD_LEN(MBEDTLS_OID_ECDSA_SHA384), "ecdsa-with-SHA384", - "ECDSA with SHA384"}, - MBEDTLS_MD_SHA384, - MBEDTLS_PK_ECDSA, - }, - { - {ADD_LEN(MBEDTLS_OID_ECDSA_SHA512), "ecdsa-with-SHA512", - "ECDSA with SHA512"}, - MBEDTLS_MD_SHA512, - MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_ECDSA_C || TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_RSA_C) - { - {ADD_LEN(MBEDTLS_OID_RSASSA_PSS), "RSASSA-PSS", "RSASSA-PSS"}, - MBEDTLS_MD_NONE, - MBEDTLS_PK_RSASSA_PSS, - }, -#endif /* MBEDTLS_RSA_C */ - { - {NULL, 0, NULL, NULL}, - MBEDTLS_MD_NONE, - MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) -FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, - sig_alg, const char *, description) -FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, - mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, - oid_sig_alg, mbedtls_pk_type_t, pk_alg, - mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ - -/* - * For PublicKeyInfo (PKCS1, RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_pk_type_t pk_alg; -} oid_pk_alg_t; - -static const oid_pk_alg_t oid_pk_alg[] = { - { - {ADD_LEN(MBEDTLS_OID_PKCS1_RSA), "rsaEncryption", "RSA"}, - MBEDTLS_PK_RSA, - }, - { - {ADD_LEN(MBEDTLS_OID_EC_ALG_UNRESTRICTED), "id-ecPublicKey", - "Generic EC key"}, - MBEDTLS_PK_ECKEY, - }, - { - {ADD_LEN(MBEDTLS_OID_EC_ALG_ECDH), "id-ecDH", "EC key for ECDH"}, - MBEDTLS_PK_ECKEY_DH, - }, - { - {NULL, 0, NULL, NULL}, - MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, - mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, - mbedtls_pk_type_t, pk_alg) - -#if defined(TINYCRYPT_PRIMITIVES) -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_uecc_group_id grp_id; -} oid_ecp_grp_t; -#else -#if defined(MBEDTLS_ECP_C) -/* - * For namedCurve (RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_ecp_group_id grp_id; -} oid_ecp_grp_t; -#endif -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -static const oid_ecp_grp_t oid_ecp_grp[] = { - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256R1), "secp256r1", "secp256r1"}, - MBEDTLS_UECC_DP_SECP256R1, - }, - { - NULL_OID_DESCRIPTOR, - MBEDTLS_UECC_DP_NONE, - }, -}; -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, - mbedtls_uecc_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, - oid_ecp_grp, mbedtls_uecc_group_id, grp_id) -#else -#if defined(MBEDTLS_ECP_C) -static const oid_ecp_grp_t oid_ecp_grp[] = { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192R1), "secp192r1", "secp192r1"}, - MBEDTLS_ECP_DP_SECP192R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224R1), "secp224r1", "secp224r1"}, - MBEDTLS_ECP_DP_SECP224R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256R1), "secp256r1", "secp256r1"}, - MBEDTLS_ECP_DP_SECP256R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP384R1), "secp384r1", "secp384r1"}, - MBEDTLS_ECP_DP_SECP384R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP521R1), "secp521r1", "secp521r1"}, - MBEDTLS_ECP_DP_SECP521R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192K1), "secp192k1", "secp192k1"}, - MBEDTLS_ECP_DP_SECP192K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224K1), "secp224k1", "secp224k1"}, - MBEDTLS_ECP_DP_SECP224K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256K1), "secp256k1", "secp256k1"}, - MBEDTLS_ECP_DP_SECP256K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_BP256R1), "brainpoolP256r1", - "brainpool256r1"}, - MBEDTLS_ECP_DP_BP256R1, - }, -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_BP384R1), "brainpoolP384r1", - "brainpool384r1"}, - MBEDTLS_ECP_DP_BP384R1, - }, -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - { - {ADD_LEN(MBEDTLS_OID_EC_GRP_BP512R1), "brainpoolP512r1", - "brainpool512r1"}, - MBEDTLS_ECP_DP_BP512R1, - }, -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - { - {NULL, 0, NULL, NULL}, - MBEDTLS_ECP_DP_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, - mbedtls_ecp_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, - oid_ecp_grp, mbedtls_ecp_group_id, grp_id) -#endif /* MBEDTLS_ECP_C */ -#endif - -#if defined(MBEDTLS_CIPHER_C) -/* - * For PKCS#5 PBES2 encryption algorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_cipher_type_t cipher_alg; -} oid_cipher_alg_t; - -static const oid_cipher_alg_t oid_cipher_alg[] = { - { - {ADD_LEN(MBEDTLS_OID_DES_CBC), "desCBC", "DES-CBC"}, - MBEDTLS_CIPHER_DES_CBC, - }, - { - {ADD_LEN(MBEDTLS_OID_DES_EDE3_CBC), "des-ede3-cbc", "DES-EDE3-CBC"}, - MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - {NULL, 0, NULL, NULL}, - MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, - mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_MD_C) -/* - * For digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; -} oid_md_alg_t; - -static const oid_md_alg_t oid_md_alg[] = { -#if defined(MBEDTLS_MD2_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD2), "id-md2", "MD2"}, - MBEDTLS_MD_MD2, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD4), "id-md4", "MD4"}, - MBEDTLS_MD_MD4, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD5), "id-md5", "MD5"}, - MBEDTLS_MD_MD5, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA1), "id-sha1", "SHA-1"}, - MBEDTLS_MD_SHA1, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA224), "id-sha224", "SHA-224"}, - MBEDTLS_MD_SHA224, - }, - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA256), "id-sha256", "SHA-256"}, - MBEDTLS_MD_SHA256, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA384), "id-sha384", "SHA-384"}, - MBEDTLS_MD_SHA384, - }, - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA512), "id-sha512", "SHA-512"}, - MBEDTLS_MD_SHA512, - }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_RIPEMD160_C) - { - {ADD_LEN(MBEDTLS_OID_DIGEST_ALG_RIPEMD160), "id-ripemd160", - "RIPEMD-160"}, - MBEDTLS_MD_RIPEMD160, - }, -#endif /* MBEDTLS_RIPEMD160_C */ - { - {NULL, 0, NULL, NULL}, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, - mbedtls_md_type_t, md_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, - mbedtls_md_type_t, md_alg) - -/* - * For HMAC digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_hmac; -} oid_md_hmac_t; - -static const oid_md_hmac_t oid_md_hmac[] = { -#if defined(MBEDTLS_SHA1_C) - { - {ADD_LEN(MBEDTLS_OID_HMAC_SHA1), "hmacSHA1", "HMAC-SHA-1"}, - MBEDTLS_MD_SHA1, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - {ADD_LEN(MBEDTLS_OID_HMAC_SHA224), "hmacSHA224", "HMAC-SHA-224"}, - MBEDTLS_MD_SHA224, - }, - { - {ADD_LEN(MBEDTLS_OID_HMAC_SHA256), "hmacSHA256", "HMAC-SHA-256"}, - MBEDTLS_MD_SHA256, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - {ADD_LEN(MBEDTLS_OID_HMAC_SHA384), "hmacSHA384", "HMAC-SHA-384"}, - MBEDTLS_MD_SHA384, - }, - { - {ADD_LEN(MBEDTLS_OID_HMAC_SHA512), "hmacSHA512", "HMAC-SHA-512"}, - MBEDTLS_MD_SHA512, - }, -#endif /* MBEDTLS_SHA512_C */ - { - {NULL, 0, NULL, NULL}, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, - mbedtls_md_type_t, md_hmac) -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PKCS12_C) -/* - * For PKCS#12 PBEs - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_cipher_type_t cipher_alg; -} oid_pkcs12_pbe_alg_t; - -static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = { - { - {ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC), - "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES"}, - MBEDTLS_MD_SHA1, - MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - {ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC), - "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES"}, - MBEDTLS_MD_SHA1, - MBEDTLS_CIPHER_DES_EDE_CBC, - }, - { - {NULL, 0, NULL, NULL}, - MBEDTLS_MD_NONE, - MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) -FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, - pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, - mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_PKCS12_C */ - -#define OID_SAFE_SNPRINTF \ - do { \ - if (ret < 0 || (size_t)ret >= n) \ - return (MBEDTLS_ERR_OID_BUF_TOO_SMALL); \ - \ - n -= (size_t)ret; \ - p += (size_t)ret; \ - } while (0) - -/* Return the x.y.z.... style numeric string for the given OID */ -int mbedtls_oid_get_numeric_string(char *buf, size_t size, - const mbedtls_asn1_buf *oid) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i, n; - unsigned int value; - char *p; - - p = buf; - n = size; - - /* First byte contains first two dots */ - if (oid->len > 0) { - ret = mbedtls_snprintf(p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40); - OID_SAFE_SNPRINTF; - } - - value = 0; - for (i = 1; i < oid->len; i++) { - /* Prevent overflow in value. */ - if (((value << 7) >> 7) != value) - return (MBEDTLS_ERR_OID_BUF_TOO_SMALL); - - value <<= 7; - value += oid->p[i] & 0x7F; - - if (!(oid->p[i] & 0x80)) { - /* Last byte */ - ret = mbedtls_snprintf(p, n, ".%u", value); - OID_SAFE_SNPRINTF; - value = 0; - } - } - - return ((int)(size - n)); -} - -#endif /* MBEDTLS_OID_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk.c b/matter/mbedtls/tinycrypt/src/pk.c deleted file mode 100644 index 6bfc165a65..0000000000 --- a/matter/mbedtls/tinycrypt/src/pk.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Public Key abstraction layer - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#include "mbedtls/pk_internal.h" - -#include "mbedtls/error.h" -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" -#endif - -#include -#include - -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) - -/* - * Initialise a mbedtls_pk_context - */ -void mbedtls_pk_init(mbedtls_pk_context *ctx) { - PK_VALIDATE(ctx != NULL); - - ctx->pk_info = NULL; - ctx->pk_ctx = NULL; -} - -/* - * Free (the components of) a mbedtls_pk_context - */ -void mbedtls_pk_free(mbedtls_pk_context *ctx) { - if (ctx == NULL) - return; - - if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { - ctx->pk_info->ctx_free_func(ctx->pk_ctx); - } - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Initialize a restart context - */ -void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) { - PK_VALIDATE(ctx != NULL); - ctx->pk_info = NULL; - ctx->rs_ctx = NULL; -} - -/* - * Free the components of a restart context - */ -void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx) { - if (ctx == NULL || ctx->pk_info == NULL || - ctx->pk_info->rs_free_func == NULL) { - return; - } - - ctx->pk_info->rs_free_func(ctx->rs_ctx); - - ctx->pk_info = NULL; - ctx->rs_ctx = NULL; -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/* - * Get pk_info structure from type - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) { - switch (pk_type) { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_PK_RSA: - return (&mbedtls_rsa_info); -#endif -#if defined(MBEDTLS_ECP_C) - case MBEDTLS_PK_ECKEY_DH: - return (&mbedtls_eckeydh_info); -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_PK_ECDSA: - return (&mbedtls_ecdsa_info); -#endif -#if defined(TINYCRYPT_PRIMITIVES) - case MBEDTLS_PK_ECKEY: - return (&mbedtls_uecc_eckey_info); -#else /* TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_ECP_C) - case MBEDTLS_PK_ECKEY: - return (&mbedtls_eckey_info); -#endif -#endif /* TINYCRYPT_PRIMITIVES */ - /* MBEDTLS_PK_RSA_ALT omitted on purpose */ - default: - return (NULL); - } -} - -/* - * Initialise context - */ -int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) { - PK_VALIDATE_RET(ctx != NULL); - if (info == NULL || ctx->pk_info != NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - - ctx->pk_info = info; - - return (0); -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Initialise a PSA-wrapping context - */ -int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, const psa_key_id_t key) { - const mbedtls_pk_info_t *const info = &mbedtls_pk_opaque_info; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t *pk_ctx; - psa_key_type_t type; - - if (ctx == NULL || ctx->pk_info != NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - type = psa_get_key_type(&attributes); - psa_reset_key_attributes(&attributes); - - /* Current implementation of can_do() relies on this. */ - if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - - ctx->pk_info = info; - - pk_ctx = (psa_key_id_t *)ctx->pk_ctx; - *pk_ctx = key; - - return (0); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Initialize an RSA-alt context - */ -int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func) { - mbedtls_rsa_alt_context *rsa_alt; - const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - - PK_VALIDATE_RET(ctx != NULL); - if (ctx->pk_info != NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - - ctx->pk_info = info; - - rsa_alt = (mbedtls_rsa_alt_context *)ctx->pk_ctx; - - rsa_alt->key = key; - rsa_alt->decrypt_func = decrypt_func; - rsa_alt->sign_func = sign_func; - rsa_alt->key_len_func = key_len_func; - - return (0); -} -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/* - * Tell if a PK can do the operations of the given type - */ -int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) { - /* A context with null pk_info is not set up yet and can't do anything. - * For backward compatibility, also accept NULL instead of a context - * pointer. */ - if (ctx == NULL || ctx->pk_info == NULL) - return (0); - - return (ctx->pk_info->can_do(type)); -} - -/* - * Helper for mbedtls_pk_sign and mbedtls_pk_verify - */ -static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, - size_t *hash_len) { - const mbedtls_md_info_t *md_info; - - if (*hash_len != 0 && md_alg == MBEDTLS_MD_NONE) - return (0); - - if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) - return (-1); - - if (*hash_len != 0 && *hash_len != mbedtls_md_get_size(md_info)) - return (-1); - - *hash_len = mbedtls_md_get_size(md_info); - return (0); -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Helper to set up a restart context if needed - */ -static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx, - const mbedtls_pk_info_t *info) { - /* Don't do anything if already set up or invalid */ - if (ctx == NULL || ctx->pk_info != NULL) - return (0); - - /* Should never happen when we're called */ - if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - - ctx->pk_info = info; - - return (0); -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/* - * Verify a signature (restartable) - */ -int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - mbedtls_pk_restart_ctx *rs_ctx) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || hash != NULL); - PK_VALIDATE_RET(sig != NULL); - - if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* optimization: use non-restartable version if restart disabled */ - if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && - ctx->pk_info->verify_rs_func != NULL) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) - return (ret); - - ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, - sig_len, rs_ctx->rs_ctx); - - if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) - mbedtls_pk_restart_free(rs_ctx); - - return (ret); - } -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - (void)rs_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - if (ctx->pk_info->verify_func == NULL) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - return (ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, - sig_len)); -} - -/* - * Verify a signature - */ -int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - return (mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len, sig, - sig_len, NULL)); -} - -/* - * Verify a signature with options - */ -int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || hash != NULL); - PK_VALIDATE_RET(sig != NULL); - - if (ctx->pk_info == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if (!mbedtls_pk_can_do(ctx, type)) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - if (type == MBEDTLS_PK_RSASSA_PSS) { -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_pk_rsassa_pss_options *pss_opts; - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); -#endif /* SIZE_MAX > UINT_MAX */ - - if (options == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - pss_opts = (const mbedtls_pk_rsassa_pss_options *)options; - - if (sig_len < mbedtls_pk_get_len(ctx)) - return (MBEDTLS_ERR_RSA_VERIFY_FAILED); - - ret = mbedtls_rsa_rsassa_pss_verify_ext( - mbedtls_pk_rsa(*ctx), NULL, NULL, MBEDTLS_RSA_PUBLIC, md_alg, - (unsigned int)hash_len, hash, pss_opts->mgf1_hash_id, - pss_opts->expected_salt_len, sig); - if (ret != 0) - return (ret); - - if (sig_len > mbedtls_pk_get_len(ctx)) - return (MBEDTLS_ERR_PK_SIG_LEN_MISMATCH); - - return (0); -#else - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); -#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ - } - - /* General case: no options */ - if (options != NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - return (mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len)); -} - -/* - * Make a signature (restartable) - */ -int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, mbedtls_pk_restart_ctx *rs_ctx) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET((md_alg == MBEDTLS_MD_NONE && hash_len == 0) || hash != NULL); - PK_VALIDATE_RET(sig != NULL); - - if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* optimization: use non-restartable version if restart disabled */ - if (rs_ctx != NULL && mbedtls_ecp_restart_is_enabled() && - ctx->pk_info->sign_rs_func != NULL) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) - return (ret); - - ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, - sig_len, f_rng, p_rng, rs_ctx->rs_ctx); - - if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) - mbedtls_pk_restart_free(rs_ctx); - - return (ret); - } -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - (void)rs_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - if (ctx->pk_info->sign_func == NULL) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - return (ctx->pk_info->sign_func(ctx->pk_ctx, md_alg, hash, hash_len, sig, - sig_len, f_rng, p_rng)); -} - -/* - * Make a signature - */ -int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - return (mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, sig, sig_len, - f_rng, p_rng, NULL)); -} - -/* - * Decrypt message - */ -int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen, - size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(input != NULL || ilen == 0); - PK_VALIDATE_RET(output != NULL || osize == 0); - PK_VALIDATE_RET(olen != NULL); - - if (ctx->pk_info == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if (ctx->pk_info->decrypt_func == NULL) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - return (ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen, output, olen, - osize, f_rng, p_rng)); -} - -/* - * Encrypt message - */ -int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen, - size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(input != NULL || ilen == 0); - PK_VALIDATE_RET(output != NULL || osize == 0); - PK_VALIDATE_RET(olen != NULL); - - if (ctx->pk_info == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if (ctx->pk_info->encrypt_func == NULL) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - return (ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen, output, olen, - osize, f_rng, p_rng)); -} - -/* - * Check public-private key pair - */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, - const mbedtls_pk_context *prv) { - PK_VALIDATE_RET(pub != NULL); - PK_VALIDATE_RET(prv != NULL); - - if (pub->pk_info == NULL || prv->pk_info == NULL) { - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - } - - if (prv->pk_info->check_pair_func == NULL) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { - if (pub->pk_info->type != MBEDTLS_PK_RSA) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - } else { - if (pub->pk_info != prv->pk_info) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - } - - return (prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx)); -} - -/* - * Get key size in bits - */ -size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) { - /* For backward compatibility, accept NULL or a context that - * isn't set up yet, and return a fake value that should be safe. */ - if (ctx == NULL || ctx->pk_info == NULL) - return (0); - - return (ctx->pk_info->get_bitlen(ctx->pk_ctx)); -} - -/* - * Export debug information - */ -int mbedtls_pk_debug(const mbedtls_pk_context *ctx, - mbedtls_pk_debug_item *items) { - PK_VALIDATE_RET(ctx != NULL); - if (ctx->pk_info == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - if (ctx->pk_info->debug_func == NULL) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - ctx->pk_info->debug_func(ctx->pk_ctx, items); - return (0); -} - -/* - * Access the PK type name - */ -const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) { - if (ctx == NULL || ctx->pk_info == NULL) - return ("invalid PK"); - - return (ctx->pk_info->name); -} - -/* - * Access the PK type - */ -mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) { - if (ctx == NULL || ctx->pk_info == NULL) - return (MBEDTLS_PK_NONE); - - return (ctx->pk_info->type); -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Load the key to a PSA key slot, - * then turn the PK context into a wrapper for that key slot. - * - * Currently only works for EC private keys. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, psa_key_id_t *key, - psa_algorithm_t hash_alg) { -#if !defined(MBEDTLS_ECP_C) - ((void)pk); - ((void)key); - ((void)hash_alg); - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); -#else - const mbedtls_ecp_keypair *ec; - unsigned char d[MBEDTLS_ECP_MAX_BYTES]; - size_t d_len; - psa_ecc_family_t curve_id; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - size_t bits; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - /* export the private key material in the format PSA wants */ - if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECKEY) - return (MBEDTLS_ERR_PK_TYPE_MISMATCH); - - ec = mbedtls_pk_ec(*pk); - d_len = (ec->grp.nbits + 7) / 8; - if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) - return (ret); - - curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); - - /* prepare the key attributes */ - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, bits); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(hash_alg)); - - /* import private key into PSA */ - if (PSA_SUCCESS != psa_import_key(&attributes, d, d_len, key)) - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return (mbedtls_pk_setup_opaque(pk, *key)); -#endif /* MBEDTLS_ECP_C */ -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk_wrap.c b/matter/mbedtls/tinycrypt/src/pk_wrap.c deleted file mode 100644 index 058e3321ca..0000000000 --- a/matter/mbedtls/tinycrypt/src/pk_wrap.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * Public Key abstraction layer: wrapper functions - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/error.h" -#include "mbedtls/pk_internal.h" - -/* Even if RSA not activated, for the sake of RSA-alt */ -#include "mbedtls/rsa.h" - -#include - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "mbedtls/asn1.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/pk.h" -#include "mbedtls/platform.h" -#include "mbedtls/platform_util.h" -#include "tinycrypt/ecc.h" -#include "tinycrypt/ecc_dsa.h" - -#if !defined(MBEDTLS_PLATFORM_C) -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/asn1write.h" -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -#include "mbedtls/platform_util.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/asn1.h" -#include "mbedtls/psa_util.h" -#include "psa/crypto.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include -#include - -#if defined(MBEDTLS_RSA_C) -static int rsa_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_RSA || type == MBEDTLS_PK_RSASSA_PSS); -} - -static size_t rsa_get_bitlen(const void *ctx) { - const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *)ctx; - return (8 * mbedtls_rsa_get_len(rsa)); -} - -static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)ctx; - size_t rsa_len = mbedtls_rsa_get_len(rsa); - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); -#endif /* SIZE_MAX > UINT_MAX */ - - if (sig_len < rsa_len) - return (MBEDTLS_ERR_RSA_VERIFY_FAILED); - - if ((ret = - mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, md_alg, - (unsigned int)hash_len, hash, sig)) != 0) - return (ret); - - /* The buffer contains a valid signature followed by extra data. - * We have a special error code for that so that so that callers can - * use mbedtls_pk_verify() to check "Does the buffer start with a - * valid signature?" and not just "Does the buffer contain a valid - * signature?". */ - if (sig_len > rsa_len) - return (MBEDTLS_ERR_PK_SIG_LEN_MISMATCH); - - return (0); -} - -static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)ctx; - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); -#endif /* SIZE_MAX > UINT_MAX */ - - *sig_len = mbedtls_rsa_get_len(rsa); - - return (mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, md_alg, - (unsigned int)hash_len, hash, sig)); -} - -static int rsa_decrypt_wrap(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)ctx; - - if (ilen != mbedtls_rsa_get_len(rsa)) - return (MBEDTLS_ERR_RSA_BAD_INPUT_DATA); - - return (mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - olen, input, output, osize)); -} - -static int rsa_encrypt_wrap(void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)ctx; - *olen = mbedtls_rsa_get_len(rsa); - - if (*olen > osize) - return (MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE); - - return (mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, - input, output)); -} - -static int rsa_check_pair_wrap(const void *pub, const void *prv) { - return (mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *)pub, - (const mbedtls_rsa_context *)prv)); -} - -static void *rsa_alloc_wrap(void) { - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); - - if (ctx != NULL) - mbedtls_rsa_init((mbedtls_rsa_context *)ctx, 0, 0); - - return (ctx); -} - -static void rsa_free_wrap(void *ctx) { - mbedtls_rsa_free((mbedtls_rsa_context *)ctx); - mbedtls_free(ctx); -} - -static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items) { - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.N"; - items->value = &(((mbedtls_rsa_context *)ctx)->N); - - items++; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.E"; - items->value = &(((mbedtls_rsa_context *)ctx)->E); -} - -const mbedtls_pk_info_t mbedtls_rsa_info = { - MBEDTLS_PK_RSA, - "RSA", - rsa_get_bitlen, - rsa_can_do, - rsa_verify_wrap, - rsa_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_decrypt_wrap, - rsa_encrypt_wrap, - rsa_check_pair_wrap, - rsa_alloc_wrap, - rsa_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_debug, -}; -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * Generic EC key - */ -static int eckey_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH || - type == MBEDTLS_PK_ECDSA); -} - -static size_t eckey_get_bitlen(const void *ctx) { - return (((mbedtls_ecp_keypair *)ctx)->grp.pbits); -} - -#if defined(MBEDTLS_ECDSA_C) -/* Forward declarations */ -static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - -static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -static int eckey_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init(&ecdsa); - - if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) - ret = ecdsa_verify_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len); - - mbedtls_ecdsa_free(&ecdsa); - - return (ret); -} - -static int eckey_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init(&ecdsa); - - if ((ret = mbedtls_ecdsa_from_keypair(&ecdsa, ctx)) == 0) - ret = ecdsa_sign_wrap(&ecdsa, md_alg, hash, hash_len, sig, sig_len, f_rng, - p_rng); - - mbedtls_ecdsa_free(&ecdsa); - - return (ret); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -/* Forward declarations */ -static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx); - -static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, void *rs_ctx); - -/* - * Restart context for ECDSA operations with ECKEY context - * - * We need to store an actual ECDSA context, as we need to pass the same to - * the underlying ecdsa function, so we can't create it on the fly every time. - */ -typedef struct { - mbedtls_ecdsa_restart_ctx ecdsa_rs; - mbedtls_ecdsa_context ecdsa_ctx; -} eckey_restart_ctx; - -static void *eckey_rs_alloc(void) { - eckey_restart_ctx *rs_ctx; - - void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); - - if (ctx != NULL) { - rs_ctx = ctx; - mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); - mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); - } - - return (ctx); -} - -static void eckey_rs_free(void *ctx) { - eckey_restart_ctx *rs_ctx; - - if (ctx == NULL) - return; - - rs_ctx = ctx; - mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); - mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); - - mbedtls_free(ctx); -} - -static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if (rs == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - /* set up our own sub-context if needed (that is, on first run) */ - if (rs->ecdsa_ctx.grp.pbits == 0) - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); - - MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx, md_alg, hash, hash_len, - sig, sig_len, &rs->ecdsa_rs)); - -cleanup: - return (ret); -} - -static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, void *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if (rs == NULL) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - /* set up our own sub-context if needed (that is, on first run) */ - if (rs->ecdsa_ctx.grp.pbits == 0) - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx)); - - MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng, - &rs->ecdsa_rs)); - -cleanup: - return (ret); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ -#endif /* MBEDTLS_ECDSA_C */ - -/* - * Internal wrappers around ECC functions - based on TinyCrypt - */ -#if defined(TINYCRYPT_PRIMITIVES) -/* - * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of - * those integers and convert it to the fixed-length encoding. - */ -static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, - unsigned char *to, size_t to_len) { - int ret; - size_t unpadded_len, padding_len; - - if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, - MBEDTLS_ASN1_INTEGER)) != 0) { - return (ret); - } - - while (unpadded_len > 0 && **from == 0x00) { - (*from)++; - unpadded_len--; - } - - if (unpadded_len > to_len || unpadded_len == 0) - return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - - padding_len = to_len - unpadded_len; - memset(to, 0x00, padding_len); - mbedtls_platform_memcpy(to + padding_len, *from, unpadded_len); - (*from) += unpadded_len; - - return (0); -} - -/* - * Convert a signature from an ASN.1 sequence of two integers - * to a raw {r,s} buffer. Note: the provided sig buffer must be at least - * twice as big as int_size. - */ -static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, - unsigned char *sig, size_t int_size) { - int ret; - size_t tmp_size; - - if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)) != 0) - return (ret); - - /* Extract r */ - if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) - return (ret); - /* Extract s */ - if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) - return (ret); - - return (0); -} - -static size_t uecc_eckey_get_bitlen(const void *ctx) { - (void)ctx; - return ((size_t)(NUM_ECC_BYTES * 8)); -} - -/* This function compares public keys of two keypairs */ -static int uecc_eckey_check_pair(const void *pub, const void *prv) { - const mbedtls_uecc_keypair *uecc_pub = (const mbedtls_uecc_keypair *)pub; - const mbedtls_uecc_keypair *uecc_prv = (const mbedtls_uecc_keypair *)prv; - - if (mbedtls_platform_memequal(uecc_pub->public_key, uecc_prv->public_key, - 2 * NUM_ECC_BYTES) == 0) { - return (0); - } - - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); -} - -static int uecc_eckey_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_ECDSA || type == MBEDTLS_PK_ECKEY); -} - -static int uecc_eckey_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; - volatile int ret_fi = UECC_FAULT_DETECTED; - uint8_t signature[2 * NUM_ECC_BYTES]; - unsigned char *p; - const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *)ctx; - - ((void)md_alg); - p = (unsigned char *)sig; - - ret = extract_ecdsa_sig(&p, sig + sig_len, signature, NUM_ECC_BYTES); - if (ret != 0) - return (ret); - - ret_fi = - uECC_verify(keypair->public_key, hash, (unsigned)hash_len, signature); - - if (ret_fi == UECC_FAULT_DETECTED) - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); - - if (ret_fi == UECC_SUCCESS) { - mbedtls_platform_random_delay(); - if (ret_fi == UECC_SUCCESS) - return (0); - else - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); - } - - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); -} - -/* - * Simultaneously convert and move raw MPI from the beginning of a buffer - * to an ASN.1 MPI at the end of the buffer. - * See also mbedtls_asn1_write_mpi(). - * - * p: pointer to the end of the output buffer - * start: start of the output buffer, and also of the mpi to write at the end - * n_len: length of the mpi to read from start - * - * Warning: - * The total length of the output buffer must be smaller than 128 Bytes. - */ -static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, - size_t n_len) { - size_t len = n_len; - int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; - - if ((size_t)(*p - start) < len) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - *p -= len; - ret = mbedtls_platform_memmove(*p, start, len); - if (ret != 0) { - return (ret); - } - - /* ASN.1 DER encoding requires minimal length, so skip leading 0s. - * Neither r nor s should be 0, but as a failsafe measure, still detect - * that rather than overflowing the buffer in case of an error. */ - while (len > 0 && **p == 0x00) { - ++(*p); - --len; - } - - /* this is only reached if the signature was invalid */ - if (len == 0) - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); - - /* if the msb is 1, ASN.1 requires that we prepend a 0. - * Neither r nor s can be 0, so we can assume len > 0 at all times. */ - if (**p & 0x80) { - if (*p - start < 1) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - *--(*p) = 0x00; - len += 1; - } - - /* Ensure that there is still space for len and ASN1_INTEGER */ - if ((*p - start) < 2) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - /* The ASN.1 length encoding is just a single Byte containing the length, - * as we assume that the total buffer length is smaller than 128 Bytes. */ - *--(*p) = len; - *--(*p) = MBEDTLS_ASN1_INTEGER; - len += 2; - - return ((int)len); -} - -/* Transcode signature from uECC format to ASN.1 sequence. - * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of - * MPIs, and in-place. - * - * [in/out] sig: the signature pre- and post-transcoding - * [in/out] sig_len: signature length pre- and post-transcoding - * [in] buf_len: the available size the in/out buffer - * - * Warning: buf_len must be smaller than 128 Bytes. - */ -static int pk_ecdsa_sig_asn1_from_uecc(unsigned char *sig, size_t *sig_len, - size_t buf_len) { - int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; - size_t len = 0; - const size_t rs_len = *sig_len / 2; - unsigned char *p = sig + buf_len; - - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); - - if (p - sig < 2) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - /* The ASN.1 length encoding is just a single Byte containing the length, - * as we assume that the total buffer length is smaller than 128 Bytes. */ - *--p = len; - *--p = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE; - len += 2; - - ret = mbedtls_platform_memmove(sig, p, len); - if (ret != 0) { - return (ret); - } - *sig_len = len; - - return (ret); -} - -static int uecc_eckey_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - const mbedtls_uecc_keypair *keypair = (const mbedtls_uecc_keypair *)ctx; - int ret; - - /* - * RFC-4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + NUM_ECC_BYTES for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * - * (The ASN.1 length encodings are all 1-Byte encodings because - * the total size is smaller than 128 Bytes). - */ -#define MAX_SECP256R1_ECDSA_SIG_LEN (3 + 2 * (3 + NUM_ECC_BYTES)) - - ret = uECC_sign(keypair->private_key, hash, hash_len, sig); - if (ret == UECC_FAULT_DETECTED) - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); - if (ret != UECC_SUCCESS) - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); - - *sig_len = 2 * NUM_ECC_BYTES; - - /* uECC owns its rng function pointer */ - (void)f_rng; - (void)p_rng; - (void)md_alg; - - return ( - pk_ecdsa_sig_asn1_from_uecc(sig, sig_len, MAX_SECP256R1_ECDSA_SIG_LEN)); - -#undef MAX_SECP256R1_ECDSA_SIG_LEN -} -static void *uecc_eckey_alloc_wrap(void) { - return (mbedtls_calloc(1, sizeof(mbedtls_uecc_keypair))); -} - -static void uecc_eckey_free_wrap(void *ctx) { - if (ctx == NULL) - return; - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_uecc_keypair)); - mbedtls_free(ctx); -} -#endif /* TINYCRYPT_PRIMITIVES */ - -static int eckey_check_pair(const void *pub, const void *prv) { - return (mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *)pub, - (const mbedtls_ecp_keypair *)prv)); -} - -static void *eckey_alloc_wrap(void) { - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); - - if (ctx != NULL) - mbedtls_ecp_keypair_init(ctx); - - return (ctx); -} - -static void eckey_free_wrap(void *ctx) { - mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *)ctx); - mbedtls_free(ctx); -} - -static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items) { - items->type = MBEDTLS_PK_DEBUG_ECP; - items->name = "eckey.Q"; - items->value = &(((mbedtls_ecp_keypair *)ctx)->Q); -} - -const mbedtls_pk_info_t mbedtls_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - eckey_get_bitlen, - eckey_can_do, -#if defined(MBEDTLS_ECDSA_C) - eckey_verify_wrap, - eckey_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - eckey_verify_rs_wrap, - eckey_sign_rs_wrap, -#endif -#else /* MBEDTLS_ECDSA_C */ - NULL, - NULL, -#endif /* MBEDTLS_ECDSA_C */ - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, - eckey_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - eckey_rs_alloc, - eckey_rs_free, -#endif - eckey_debug, -}; - -/* - * EC key restricted to ECDH - */ -static int eckeydh_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECKEY_DH); -} - -const mbedtls_pk_info_t mbedtls_eckeydh_info = { - MBEDTLS_PK_ECKEY_DH, - "EC_DH", - eckey_get_bitlen, /* Same underlying key structure */ - eckeydh_can_do, - NULL, - NULL, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, /* Same underlying key structure */ - eckey_free_wrap, /* Same underlying key structure */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - eckey_debug, /* Same underlying key structure */ -}; -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_ECDSA_C) -static int ecdsa_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_ECDSA); -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of - * those integers and convert it to the fixed-length encoding expected by PSA. - */ -static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, - unsigned char *to, size_t to_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t unpadded_len, padding_len; - - if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, - MBEDTLS_ASN1_INTEGER)) != 0) { - return (ret); - } - - while (unpadded_len > 0 && **from == 0x00) { - (*from)++; - unpadded_len--; - } - - if (unpadded_len > to_len || unpadded_len == 0) - return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - - padding_len = to_len - unpadded_len; - memset(to, 0x00, padding_len); - memcpy(to + padding_len, *from, unpadded_len); - (*from) += unpadded_len; - - return (0); -} - -/* - * Convert a signature from an ASN.1 sequence of two integers - * to a raw {r,s} buffer. Note: the provided sig buffer must be at least - * twice as big as int_size. - */ -static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, - unsigned char *sig, size_t int_size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t tmp_size; - - if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)) != 0) - return (ret); - - /* Extract r */ - if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) - return (ret); - /* Extract s */ - if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) - return (ret); - - return (0); -} - -static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - mbedtls_ecdsa_context *ctx = ctx_arg; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t key_id = 0; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ - unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; - unsigned char *p; - mbedtls_pk_info_t pk_info = mbedtls_eckey_info; - psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; - size_t curve_bits; - psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); - const size_t signature_part_size = (ctx->grp.nbits + 7) / 8; - ((void)md_alg); - - if (curve == 0) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - /* mbedtls_pk_write_pubkey() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &pk_info; - key.pk_ctx = ctx; - p = buf + sizeof(buf); - key_len = mbedtls_pk_write_pubkey(&p, buf, &key); - if (key_len <= 0) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, psa_sig_md); - - status = psa_import_key(&attributes, buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = mbedtls_psa_err_translate_pk(status); - goto cleanup; - } - - /* We don't need the exported key anymore and can - * reuse its buffer for signature extraction. */ - if (2 * signature_part_size > sizeof(buf)) { - ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; - goto cleanup; - } - - p = (unsigned char *)sig; - if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf, signature_part_size)) != - 0) { - goto cleanup; - } - - if (psa_verify_hash(key_id, psa_sig_md, hash, hash_len, buf, - 2 * signature_part_size) != PSA_SUCCESS) { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - if (p != sig + sig_len) { - ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - goto cleanup; - } - ret = 0; - -cleanup: - psa_destroy_key(key_id); - return (ret); -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ((void)md_alg); - - ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *)ctx, hash, - hash_len, sig, sig_len); - - if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) - return (MBEDTLS_ERR_PK_SIG_LEN_MISMATCH); - - return (ret); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - return (mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *)ctx, md_alg, - hash, hash_len, sig, sig_len, f_rng, - p_rng)); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ((void)md_alg); - - ret = mbedtls_ecdsa_read_signature_restartable( - (mbedtls_ecdsa_context *)ctx, hash, hash_len, sig, sig_len, - (mbedtls_ecdsa_restart_ctx *)rs_ctx); - - if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) - return (MBEDTLS_ERR_PK_SIG_LEN_MISMATCH); - - return (ret); -} - -static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, void *rs_ctx) { - return (mbedtls_ecdsa_write_signature_restartable( - (mbedtls_ecdsa_context *)ctx, md_alg, hash, hash_len, sig, sig_len, f_rng, - p_rng, (mbedtls_ecdsa_restart_ctx *)rs_ctx)); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ - -static void *ecdsa_alloc_wrap(void) { - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_context)); - - if (ctx != NULL) - mbedtls_ecdsa_init((mbedtls_ecdsa_context *)ctx); - - return (ctx); -} - -static void ecdsa_free_wrap(void *ctx) { - mbedtls_ecdsa_free((mbedtls_ecdsa_context *)ctx); - mbedtls_free(ctx); -} - -#if defined(MBEDTLS_ECP_RESTARTABLE) -static void *ecdsa_rs_alloc(void) { - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); - - if (ctx != NULL) - mbedtls_ecdsa_restart_init(ctx); - - return (ctx); -} - -static void ecdsa_rs_free(void *ctx) { - mbedtls_ecdsa_restart_free(ctx); - mbedtls_free(ctx); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ - -const mbedtls_pk_info_t mbedtls_ecdsa_info = { - MBEDTLS_PK_ECDSA, - "ECDSA", - eckey_get_bitlen, /* Compatible key structures */ - ecdsa_can_do, - ecdsa_verify_wrap, - ecdsa_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_verify_rs_wrap, - ecdsa_sign_rs_wrap, -#endif - NULL, - NULL, - eckey_check_pair, /* Compatible key structures */ - ecdsa_alloc_wrap, - ecdsa_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - ecdsa_rs_alloc, - ecdsa_rs_free, -#endif - eckey_debug, /* Compatible key structures */ -}; -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(TINYCRYPT_PRIMITIVES) -const mbedtls_pk_info_t mbedtls_uecc_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - uecc_eckey_get_bitlen, /* Compatible key structures */ - uecc_eckey_can_do, - uecc_eckey_verify_wrap, - uecc_eckey_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, - NULL, - uecc_eckey_check_pair, /* Compatible key structures */ - uecc_eckey_alloc_wrap, - uecc_eckey_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, /* Compatible key structures */ -}; -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Support for alternative RSA-private implementations - */ - -static int rsa_alt_can_do(mbedtls_pk_type_t type) { - return (type == MBEDTLS_PK_RSA); -} - -static size_t rsa_alt_get_bitlen(const void *ctx) { - const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *)ctx; - - return (8 * rsa_alt->key_len_func(rsa_alt->key)); -} - -static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *)ctx; - -#if SIZE_MAX > UINT_MAX - if (UINT_MAX < hash_len) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); -#endif /* SIZE_MAX > UINT_MAX */ - - *sig_len = rsa_alt->key_len_func(rsa_alt->key); - if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - return (rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int)hash_len, hash, sig)); -} - -static int rsa_alt_decrypt_wrap(void *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, - size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *)ctx; - - ((void)f_rng); - ((void)p_rng); - - if (ilen != rsa_alt->key_len_func(rsa_alt->key)) - return (MBEDTLS_ERR_RSA_BAD_INPUT_DATA); - - return (rsa_alt->decrypt_func(rsa_alt->key, MBEDTLS_RSA_PRIVATE, olen, input, - output, osize)); -} - -#if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair(const void *pub, const void *prv) { - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char hash[32]; - size_t sig_len = 0; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) - return (MBEDTLS_ERR_RSA_KEY_CHECK_FAILED); - - memset(hash, 0x2a, sizeof(hash)); - - if ((ret = rsa_alt_sign_wrap((void *)prv, MBEDTLS_MD_NONE, hash, sizeof(hash), - sig, &sig_len, NULL, NULL)) != 0) { - return (ret); - } - - if (rsa_verify_wrap((void *)pub, MBEDTLS_MD_NONE, hash, sizeof(hash), sig, - sig_len) != 0) { - return (MBEDTLS_ERR_RSA_KEY_CHECK_FAILED); - } - - return (0); -} -#endif /* MBEDTLS_RSA_C */ - -static void *rsa_alt_alloc_wrap(void) { - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); - - if (ctx != NULL) - memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); - - return (ctx); -} - -static void rsa_alt_free_wrap(void *ctx) { - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context)); - mbedtls_free(ctx); -} - -const mbedtls_pk_info_t mbedtls_rsa_alt_info = { - MBEDTLS_PK_RSA_ALT, - "RSA-alt", - rsa_alt_get_bitlen, - rsa_alt_can_do, - NULL, - rsa_alt_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - rsa_alt_decrypt_wrap, - NULL, -#if defined(MBEDTLS_RSA_C) - rsa_alt_check_pair, -#else - NULL, -#endif - rsa_alt_alloc_wrap, - rsa_alt_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif - NULL, -}; - -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - -static void *pk_opaque_alloc_wrap(void) { - void *ctx = mbedtls_calloc(1, sizeof(psa_key_id_t)); - - /* no _init() function to call, an calloc() already zeroized */ - - return (ctx); -} - -static void pk_opaque_free_wrap(void *ctx) { - mbedtls_platform_zeroize(ctx, sizeof(psa_key_id_t)); - mbedtls_free(ctx); -} - -static size_t pk_opaque_get_bitlen(const void *ctx) { - const psa_key_id_t *key = (const psa_key_id_t *)ctx; - size_t bits; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - - if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) - return (0); - - bits = psa_get_key_bits(&attributes); - psa_reset_key_attributes(&attributes); - return (bits); -} - -static int pk_opaque_can_do(mbedtls_pk_type_t type) { - /* For now opaque PSA keys can only wrap ECC keypairs, - * as checked by setup_psa(). - * Also, ECKEY_DH does not really make sense with the current API. */ - return (type == MBEDTLS_PK_ECKEY || type == MBEDTLS_PK_ECDSA); -} - -#if defined(MBEDTLS_ECDSA_C) - -/* - * Simultaneously convert and move raw MPI from the beginning of a buffer - * to an ASN.1 MPI at the end of the buffer. - * See also mbedtls_asn1_write_mpi(). - * - * p: pointer to the end of the output buffer - * start: start of the output buffer, and also of the mpi to write at the end - * n_len: length of the mpi to read from start - */ -static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, - size_t n_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - - if ((size_t)(*p - start) < n_len) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - len = n_len; - *p -= len; - memmove(*p, start, len); - - /* ASN.1 DER encoding requires minimal length, so skip leading 0s. - * Neither r nor s should be 0, but as a failsafe measure, still detect - * that rather than overflowing the buffer in case of a PSA error. */ - while (len > 0 && **p == 0x00) { - ++(*p); - --len; - } - - /* this is only reached if the signature was invalid */ - if (len == 0) - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); - - /* if the msb is 1, ASN.1 requires that we prepend a 0. - * Neither r nor s can be 0, so we can assume len > 0 at all times. */ - if (**p & 0x80) { - if (*p - start < 1) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER)); - - return ((int)len); -} - -/* Transcode signature from PSA format to ASN.1 sequence. - * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of - * MPIs, and in-place. - * - * [in/out] sig: the signature pre- and post-transcoding - * [in/out] sig_len: signature length pre- and post-transcoding - * [int] buf_len: the available size the in/out buffer - */ -static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len, - size_t buf_len) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - const size_t rs_len = *sig_len / 2; - unsigned char *p = sig + buf_len; - - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - memmove(sig, p, len); - *sig_len = len; - - return (0); -} - -#endif /* MBEDTLS_ECDSA_C */ - -static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { -#if !defined(MBEDTLS_ECDSA_C) - ((void)ctx); - ((void)md_alg); - ((void)hash); - ((void)hash_len); - ((void)sig); - ((void)sig_len); - ((void)f_rng); - ((void)p_rng); - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); -#else /* !MBEDTLS_ECDSA_C */ - const psa_key_id_t *key = (const psa_key_id_t *)ctx; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t alg = PSA_ALG_ECDSA(mbedtls_psa_translate_md(md_alg)); - size_t buf_len; - psa_status_t status; - - /* PSA has its own RNG */ - (void)f_rng; - (void)p_rng; - - /* PSA needs an output buffer of known size, but our API doesn't provide - * that information. Assume that the buffer is large enough for a - * maximal-length signature with that key (otherwise the application is - * buggy anyway). */ - status = psa_get_key_attributes(*key, &attributes); - if (status != PSA_SUCCESS) - return (mbedtls_psa_err_translate_pk(status)); - buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN(psa_get_key_bits(&attributes)); - psa_reset_key_attributes(&attributes); - if (buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - /* make the signature */ - status = psa_sign_hash(*key, alg, hash, hash_len, sig, buf_len, sig_len); - if (status != PSA_SUCCESS) - return (mbedtls_psa_err_translate_pk(status)); - - /* transcode it to ASN.1 sequence */ - return (pk_ecdsa_sig_asn1_from_psa(sig, sig_len, buf_len)); -#endif /* !MBEDTLS_ECDSA_C */ -} - -const mbedtls_pk_info_t mbedtls_pk_opaque_info = { - MBEDTLS_PK_OPAQUE, - "Opaque", - pk_opaque_get_bitlen, - pk_opaque_can_do, - NULL, /* verify - will be done later */ - pk_opaque_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, /* restartable verify - not relevant */ - NULL, /* restartable sign - not relevant */ -#endif - NULL, /* decrypt - will be done later */ - NULL, /* encrypt - will be done later */ - NULL, /* check_pair - could be done later or left NULL */ - pk_opaque_alloc_wrap, - pk_opaque_free_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - NULL, /* restart alloc - not relevant */ - NULL, /* restart free - not relevant */ -#endif - NULL, /* debug - could be done later, or even left NULL */ -}; - -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pkparse.c b/matter/mbedtls/tinycrypt/src/pkparse.c deleted file mode 100644 index c52ccb38d3..0000000000 --- a/matter/mbedtls/tinycrypt/src/pkparse.c +++ /dev/null @@ -1,1672 +0,0 @@ -/* - * Public Key layer for parsing key files and structures - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_PARSE_C) - -#include "mbedtls/asn1.h" -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/pk.h" -#include "mbedtls/platform_util.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif -#if defined(TINYCRYPT_PRIMITIVES) -#include "tinycrypt/ecc.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) - -#if defined(MBEDTLS_FS_IO) -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) { - FILE *f; - long size; - - PK_VALIDATE_RET(path != NULL); - PK_VALIDATE_RET(buf != NULL); - PK_VALIDATE_RET(n != NULL); - - if ((f = fopen(path, "rb")) == NULL) - return (MBEDTLS_ERR_PK_FILE_IO_ERROR); - - fseek(f, 0, SEEK_END); - if ((size = ftell(f)) == -1) { - fclose(f); - return (MBEDTLS_ERR_PK_FILE_IO_ERROR); - } - fseek(f, 0, SEEK_SET); - - *n = (size_t)size; - - if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { - fclose(f); - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - } - - if (fread(*buf, 1, *n, f) != *n) { - fclose(f); - - mbedtls_platform_zeroize(*buf, *n); - mbedtls_free(*buf); - - return (MBEDTLS_ERR_PK_FILE_IO_ERROR); - } - - fclose(f); - - (*buf)[*n] = '\0'; - - if (strstr((const char *)*buf, "-----BEGIN ") != NULL) - ++*n; - - return (0); -} - -/* - * Load and parse a private key - */ -int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, const char *path, - const char *pwd) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(path != NULL); - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) - return (ret); - - if (pwd == NULL) - ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0); - else - ret = mbedtls_pk_parse_key(ctx, buf, n, (const unsigned char *)pwd, - strlen(pwd)); - - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); - - return (ret); -} - -/* - * Load and parse a public key - */ -int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - PK_VALIDATE_RET(ctx != NULL); - PK_VALIDATE_RET(path != NULL); - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) - return (ret); - - ret = mbedtls_pk_parse_public_key(ctx, buf, n); - - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); - - return (ret); -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(TINYCRYPT_PRIMITIVES) -static int pk_use_ecparams(const mbedtls_asn1_buf *params) { - mbedtls_uecc_group_id grp_id; - - if (params->tag == MBEDTLS_ASN1_OID) { - if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) - return (MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE); - } else { - // Only P-256 is supported - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - } - - return (0); -} -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) -/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - * } - */ -static int pk_get_ecparams(unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (end - *p < 1) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_OUT_OF_DATA)); - - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if (params->tag != MBEDTLS_ASN1_OID -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) -#endif - ) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)); - } - - if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - params->p = *p; - *p += params->len; - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} -#endif /* MBEDTLS_ECP_C || TINYCRYPT_PRIMITIVES */ - -#if !defined(TINYCRYPT_PRIMITIVES) - -#if defined(MBEDTLS_ECP_C) -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. - * WARNING: the resulting group should only be used with - * pk_group_id_from_specified(), since its base point may not be set correctly - * if it was encoded compressed. - * - * SpecifiedECDomain ::= SEQUENCE { - * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), - * fieldID FieldID {{FieldTypes}}, - * curve Curve, - * base ECPoint, - * order INTEGER, - * cofactor INTEGER OPTIONAL, - * hash HashAlgorithm OPTIONAL, - * ... - * } - * - * We only support prime-field as field type, and ignore hash and cofactor. - */ -static int pk_group_from_specified(const mbedtls_asn1_buf *params, - mbedtls_ecp_group *grp) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *p = params->p; - const unsigned char *const end = params->p + params->len; - const unsigned char *end_field, *end_curve; - size_t len; - int ver; - - /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ - if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if (ver < 1 || ver > 3) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - - /* - * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field - * fieldType FIELD-ID.&id({IOSet}), - * parameters FIELD-ID.&Type({IOSet}{@fieldType}) - * } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (ret); - - end_field = p + len; - - /* - * FIELD-ID ::= TYPE-IDENTIFIER - * FieldTypes FIELD-ID ::= { - * { Prime-p IDENTIFIED BY prime-field } | - * { Characteristic-two IDENTIFIED BY characteristic-two-field } - * } - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) - return (ret); - - if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || - memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - } - - p += len; - - /* Prime-p ::= INTEGER -- Field of size p. */ - if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - grp->pbits = mbedtls_mpi_bitlen(&grp->P); - - if (p != end_field) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* - * Curve ::= SEQUENCE { - * a FieldElement, - * b FieldElement, - * seed BIT STRING OPTIONAL - * -- Shall be present if used in SpecifiedECDomain - * -- with version equal to ecdpVer2 or ecdpVer3 - * } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (ret); - - end_curve = p + len; - - /* - * FieldElement ::= OCTET STRING - * containing an integer in the case of a prime field - */ - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0 || - (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - p += len; - - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0 || - (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - p += len; - - /* Ignore seed BIT STRING OPTIONAL */ - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, - MBEDTLS_ASN1_BIT_STRING)) == 0) - p += len; - - if (p != end_curve) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* - * ECPoint ::= OCTET STRING - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if ((ret = mbedtls_ecp_point_read_binary( - grp, &grp->G, (const unsigned char *)p, len)) != 0) { - /* - * If we can't read the point because it's compressed, cheat by - * reading only the X coordinate and the parity bit of Y. - */ - if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || - (p[0] != 0x02 && p[0] != 0x03) || - len != mbedtls_mpi_size(&grp->P) + 1 || - mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || - mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || - mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - } - } - - p += len; - - /* - * order INTEGER - */ - if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - grp->nbits = mbedtls_mpi_bitlen(&grp->N); - - /* - * Allow optional elements by purposefully not enforcing p == end here. - */ - - return (0); -} - -/* - * Find the group id associated with an (almost filled) group as generated by - * pk_group_from_specified(), or return an error if unknown. - */ -static int pk_group_id_from_group(const mbedtls_ecp_group *grp, - mbedtls_ecp_group_id *grp_id) { - int ret = 0; - mbedtls_ecp_group ref; - const mbedtls_ecp_group_id *id; - - mbedtls_ecp_group_init(&ref); - - for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { - /* Load the group associated to that id */ - mbedtls_ecp_group_free(&ref); - MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); - - /* Compare to the group we were given, starting with easy tests */ - if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && - mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && - mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && - mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && - mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && - mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && - mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && - /* For Y we may only know the parity bit, so compare only that */ - mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { - break; - } - } - -cleanup: - mbedtls_ecp_group_free(&ref); - - *grp_id = *id; - - if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - - return (ret); -} - -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID - */ -static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_group grp; - - mbedtls_ecp_group_init(&grp); - - if ((ret = pk_group_from_specified(params, &grp)) != 0) - goto cleanup; - - ret = pk_group_id_from_group(&grp, grp_id); - -cleanup: - mbedtls_ecp_group_free(&grp); - - return (ret); -} -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ - -/* - * Use EC parameters to initialise an EC group - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - */ -static int pk_use_ecparams(const mbedtls_asn1_buf *params, - mbedtls_ecp_group *grp) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_group_id grp_id; - - if (params->tag == MBEDTLS_ASN1_OID) { - if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) - return (MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE); - } else { -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) - return (ret); -#else - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); -#endif - } - - /* - * grp may already be initialized; if so, make sure IDs match - */ - if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - - if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) - return (ret); - - return (0); -} - -/* - * EC public key is an EC point - * - * The caller is responsible for clearing the structure upon failure if - * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE - * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. - */ -static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, - mbedtls_ecp_keypair *key) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = mbedtls_ecp_point_read_binary( - &key->grp, &key->Q, (const unsigned char *)*p, end - *p)) == 0) { - ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q); - } - - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *)end; - - return (ret); -} -#endif /* MBEDTLS_ECP_C */ -#endif /* !TINYCRYPT_PRIMITIVES */ - -#if defined(TINYCRYPT_PRIMITIVES) -/* - * Import a point from unsigned binary data (SEC1 2.3.4) - */ -static int uecc_public_key_read_binary(mbedtls_uecc_keypair *uecc_keypair, - const unsigned char *buf, size_t ilen) { - if (ilen != 2 * NUM_ECC_BYTES + 1) - return (MBEDTLS_ERR_PK_INVALID_PUBKEY); - - /* We are not handling the point at infinity. */ - - if (buf[0] != 0x04) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - if (mbedtls_platform_memcpy(uecc_keypair->public_key, buf + 1, - 2 * NUM_ECC_BYTES) == uecc_keypair->public_key) { - return (0); - } - - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); -} - -static int pk_get_ueccpubkey(unsigned char **p, const unsigned char *end, - uint8_t *pk_context) { - mbedtls_uecc_keypair *uecc_keypair = (mbedtls_uecc_keypair *)pk_context; - int ret; - - if ((ret = uecc_public_key_read_binary( - uecc_keypair, (const unsigned char *)*p, end - *p)) != 0) - return ret; - - /* - * We know uecc_public_key_read_binary consumed all bytes or failed - */ - *p = (unsigned char *)end; - - return (ret); -} -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_get_rsapubkey(unsigned char **p, const unsigned char *end, - mbedtls_rsa_context *rsa) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret)); - - if (*p + len != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* Import N */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret)); - - if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, NULL, 0, - NULL, 0)) != 0) - return (MBEDTLS_ERR_PK_INVALID_PUBKEY); - - *p += len; - - /* Import E */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret)); - - if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, NULL, 0, *p, - len)) != 0) - return (MBEDTLS_ERR_PK_INVALID_PUBKEY); - - *p += len; - - if (mbedtls_rsa_complete(rsa) != 0 || mbedtls_rsa_check_pubkey(rsa) != 0) { - return (MBEDTLS_ERR_PK_INVALID_PUBKEY); - } - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} -#endif /* MBEDTLS_RSA_C */ - -/* Get a PK algorithm identifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -static int pk_get_pk_alg(unsigned char **p, const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_asn1_buf alg_oid; - - memset(params, 0, sizeof(mbedtls_asn1_buf)); - - if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret)); - - if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - - /* - * No parameters with RSA (only for EC) - */ - if (*pk_alg == MBEDTLS_PK_RSA && - ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || - params->len != 0)) { - return (MBEDTLS_ERR_PK_INVALID_ALG); - } - - return (0); -} - -/* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ -int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - mbedtls_asn1_buf alg_params; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - PK_VALIDATE_RET(p != NULL); - PK_VALIDATE_RET(*p != NULL); - PK_VALIDATE_RET(end != NULL); - PK_VALIDATE_RET(pk != NULL); - - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - end = *p + len; - - if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) - return (ret); - - if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret)); - - if (*p + len != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) - return (ret); - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA) { - ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(TINYCRYPT_PRIMITIVES) - if (pk_alg == MBEDTLS_PK_ECKEY) { - ret = pk_get_ueccpubkey(p, end, (uint8_t *)pk->pk_ctx); - } else -#else /* TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_ECP_C) - if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { - ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp); - if (ret == 0) - ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk)); - } else -#endif /* MBEDTLS_ECP_C */ -#endif /* TINYCRYPT_PRIMITIVES */ - ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - - if (ret == 0 && *p != end) - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - - if (ret != 0) - mbedtls_pk_free(pk); - - return (ret); -} - -#if defined(MBEDTLS_RSA_C) -/* - * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. - * - * The value zero is: - * - never a valid value for an RSA parameter - * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). - * - * Since values can't be omitted in PKCS#1, passing a zero value to - * rsa_complete() would be incorrect, so reject zero values early. - */ -static int asn1_get_nonzero_mpi(unsigned char **p, const unsigned char *end, - mbedtls_mpi *X) { - int ret; - - ret = mbedtls_asn1_get_mpi(p, end, X); - if (ret != 0) - return (ret); - - if (mbedtls_mpi_cmp_int(X, 0) == 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - - return (0); -} - -/* - * Parse a PKCS#1 encoded private RSA key - */ -static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, - const unsigned char *key, size_t keylen) { - int ret, version; - size_t len; - unsigned char *p, *end; - - mbedtls_mpi T; - mbedtls_mpi_init(&T); - - p = (unsigned char *)key; - end = p + keylen; - - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - if (version != 0) { - return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION); - } - - /* Import N */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, NULL, NULL)) != 0) - goto cleanup; - - /* Import E */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, NULL, &T)) != 0) - goto cleanup; - - /* Import D */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, &T, NULL)) != 0) - goto cleanup; - - /* Import P */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, NULL, NULL)) != 0) - goto cleanup; - - /* Import Q */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, NULL, NULL)) != 0) - goto cleanup; - -#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) - /* - * The RSA CRT parameters DP, DQ and QP are nominally redundant, in - * that they can be easily recomputed from D, P and Q. However by - * parsing them from the PKCS1 structure it is possible to avoid - * recalculating them which both reduces the overhead of loading - * RSA private keys into memory and also avoids side channels which - * can arise when computing those values, since all of D, P, and Q - * are secret. See https://eprint.iacr.org/2020/055 for a - * description of one such attack. - */ - - /* Import DP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) - goto cleanup; - - /* Import DQ */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) - goto cleanup; - - /* Import QP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) - goto cleanup; - -#else - /* Verify existence of the CRT params */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) - goto cleanup; -#endif - - /* rsa_complete() doesn't complete anything with the default - * implementation but is still called: - * - for the benefit of alternative implementation that may want to - * pre-compute stuff beyond what's provided (eg Montgomery factors) - * - as is also sanity-checks the key - * - * Furthermore, we also check the public part for consistency with - * mbedtls_pk_parse_pubkey(), as it includes size minima for example. - */ - if ((ret = mbedtls_rsa_complete(rsa)) != 0 || - (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { - goto cleanup; - } - - if (p != end) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - -cleanup: - - mbedtls_mpi_free(&T); - - if (ret != 0) { - /* Wrap error code if it's coming from a lower level */ - if ((ret & 0xff80) == 0) - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - else - ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - - mbedtls_rsa_free(rsa); - } - - return (ret); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(TINYCRYPT_PRIMITIVES) -static int pk_parse_key_sec1_der(mbedtls_uecc_keypair *keypair, - const unsigned char *key, size_t keylen) { - int ret; - int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *)key; - unsigned char *end = p + keylen; - unsigned char *end2; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - - if (version != 1) - return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION); - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - - if (mbedtls_platform_memcpy(keypair->private_key, p, len) != - keypair->private_key) { - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); - } - - p += len; - - pubkey_done = 0; - if (p != end) { - /* - * Is 'parameters' present? - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { - if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || - (ret = pk_use_ecparams(¶ms)) != 0) { - return (ret); - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - } - } - - if (p != end) { - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { - end2 = p + len; - - if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - - if (p + len != end2) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - - if ((ret = uecc_public_key_read_binary(keypair, (const unsigned char *)p, - end2 - p)) == 0) { - pubkey_done = 1; - } else { - /* - * The only acceptable failure mode of - * uecc_public_key_read_binary() above - * is if the point format is not recognized. - */ - if (ret != MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret); - } - } - - if (!pubkey_done) { - ret = uECC_compute_public_key(keypair->private_key, keypair->public_key); - if (ret == UECC_FAULT_DETECTED) - return (MBEDTLS_ERR_PLATFORM_FAULT_DETECTED); - if (ret != UECC_SUCCESS) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - } - - return (0); -} -#else /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_ECP_C) -/* - * Parse a SEC1 encoded private EC key - */ -static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck, - const unsigned char *key, size_t keylen) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *)key; - unsigned char *end = p + keylen; - unsigned char *end2; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if (version != 1) - return (MBEDTLS_ERR_PK_KEY_INVALID_VERSION); - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) { - mbedtls_ecp_keypair_free(eck); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - p += len; - - pubkey_done = 0; - if (p != end) { - /* - * Is 'parameters' present? - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)) == 0) { - if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || - (ret = pk_use_ecparams(¶ms, &eck->grp)) != 0) { - mbedtls_ecp_keypair_free(eck); - return (ret); - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - mbedtls_ecp_keypair_free(eck); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - } - - if (p != end) { - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 1)) == 0) { - end2 = p + len; - - if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if (p + len != end2) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) - pubkey_done = 1; - else { - /* - * The only acceptable failure mode of pk_get_ecpubkey() above - * is if the point format is not recognized. - */ - if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - mbedtls_ecp_keypair_free(eck); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - } - - if (!pubkey_done && (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, - &eck->grp.G, NULL, NULL)) != 0) { - mbedtls_ecp_keypair_free(eck); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) { - mbedtls_ecp_keypair_free(eck); - return (ret); - } - - return (0); -} -#endif /* MBEDTLS_ECP_C */ -#endif /* TINYCRYPT_PRIMITIVES */ - -/* - * Parse an unencrypted PKCS#8 encoded private key - * - * Notes: - * - * - This function does not own the key buffer. It is the - * responsibility of the caller to take care of zeroizing - * and freeing it after use. - * - * - The function is responsible for freeing the provided - * PK context on failure. - * - */ -static int pk_parse_key_pkcs8_unencrypted_der(mbedtls_pk_context *pk, - const unsigned char *key, - size_t keylen) { - int ret, version; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *)key; - unsigned char *end = p + keylen; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - /* - * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey - */ - - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if (version != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret)); - - if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms)) != 0) { - return (ret); - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if (len < 1) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_OUT_OF_DATA)); - - if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) - return (ret); - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA) { - if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { - mbedtls_pk_free(pk); - return (ret); - } - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(TINYCRYPT_PRIMITIVES) - if (pk_alg == MBEDTLS_PK_ECKEY) { - if ((ret = pk_use_ecparams(¶ms)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_uecc(*pk), p, len)) != 0) { - return (ret); - } - } else -#else /* TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_ECP_C) - if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { - if ((ret = pk_use_ecparams(¶ms, &mbedtls_pk_ec(*pk)->grp)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len)) != 0) { - mbedtls_pk_free(pk); - return (ret); - } - } else -#endif /* MBEDTLS_ECP_C */ -#endif /* TINYCRYPT_PRIMITIVES */ - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - - return (0); -} - -/* - * Parse an encrypted PKCS#8 encoded private key - * - * To save space, the decryption happens in-place on the given key buffer. - * Also, while this function may modify the keybuffer, it doesn't own it, - * and instead it is the responsibility of the caller to zeroize and properly - * free it after use. - * - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -static int pk_parse_key_pkcs8_encrypted_der(mbedtls_pk_context *pk, - unsigned char *key, size_t keylen, - const unsigned char *pwd, - size_t pwdlen) { - int ret, decrypted = 0; - size_t len; - unsigned char *buf; - unsigned char *p, *end; - mbedtls_asn1_buf pbe_alg_oid, pbe_params; -#if defined(MBEDTLS_PKCS12_C) - mbedtls_cipher_type_t cipher_alg; - mbedtls_md_type_t md_alg; -#endif - - p = key; - end = p + keylen; - - if (pwdlen == 0) - return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); - - /* - * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData - * } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - * - * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo - * - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret)); - - buf = p; - - /* - * Decrypt EncryptedData with appropriate PBE - */ -#if defined(MBEDTLS_PKCS12_C) - if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { - if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, pwd, pwdlen, p, len, - buf)) != 0) { - if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) - return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - - return (ret); - } - - decrypted = 1; - } else if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, - &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs12_pbe_sha1_rc4_128(&pbe_params, - MBEDTLS_PKCS12_PBE_DECRYPT, pwd, - pwdlen, p, len, buf)) != 0) { - return (ret); - } - - // Best guess for password mismatch when using RC4. If first tag is - // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE - // - if (*buf != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) - return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - - decrypted = 1; - } else -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PKCS5_C) - if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, - pwdlen, p, len, buf)) != 0) { - if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) - return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - - return (ret); - } - - decrypted = 1; - } else -#endif /* MBEDTLS_PKCS5_C */ - { - ((void)pwd); - } - - if (decrypted == 0) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - return (pk_parse_key_pkcs8_unencrypted_der(pk, buf, len)); -} -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - -/* - * Parse a private key - */ -int mbedtls_pk_parse_key(mbedtls_pk_context *pk, const unsigned char *key, - size_t keylen, const unsigned char *pwd, - size_t pwdlen) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_pk_info_t *pk_info; -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; -#endif - - PK_VALIDATE_RET(pk != NULL); - if (keylen == 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - PK_VALIDATE_RET(key != NULL); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init(&pem); - -#if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", key, pwd, - pwdlen, &len); - - if (ret == 0) { - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), pem.buf, - pem.buflen)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return (ret); - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) - return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) - return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) - return (ret); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", key, pwd, - pwdlen, &len); - if (ret == 0) { - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - -#if defined(TINYCRYPT_PRIMITIVES) - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_uecc(*pk), pem.buf, - pem.buflen)) != 0) -#else /* TINYCRYPT_PRIMITIVES */ - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), pem.buf, - pem.buflen)) != 0) -#endif /* TINYCRYPT_PRIMITIVES */ - { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return (ret); - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) - return (MBEDTLS_ERR_PK_PASSWORD_MISMATCH); - else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) - return (MBEDTLS_ERR_PK_PASSWORD_REQUIRED); - else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) - return (ret); -#endif /* MBEDTLS_ECP_C || TINYCRYPT_PRIMITIVES */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", key, NULL, 0, - &len); - if (ret == 0) { - if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, pem.buf, pem.buflen)) != - 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return (ret); - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) - return (ret); - -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", key, - NULL, 0, &len); - if (ret == 0) { - if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, pwd, - pwdlen)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return (ret); - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) - return (ret); -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ -#else - ((void)pwd); - ((void)pwdlen); -#endif /* MBEDTLS_PEM_PARSE_C */ - - /* - * At this point we only know it's not a PEM formatted key. Could be any - * of the known DER encoded private key formats - * - * We try the different DER format parsers to see if one passes without - * error - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - { - unsigned char *key_copy; - - if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) - return (MBEDTLS_ERR_PK_ALLOC_FAILED); - - memcpy(key_copy, key, keylen); - - ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, pwd, pwdlen); - - mbedtls_platform_zeroize(key_copy, keylen); - mbedtls_free(key_copy); - } - - if (ret == 0) - return (0); - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { - return (ret); - } -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - - ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen); - if (ret == 0) { - return (0); - } - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - -#if defined(MBEDTLS_RSA_C) - - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); - if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) { - return (0); - } - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); -#endif /* MBEDTLS_RSA_C */ - -#if defined(TINYCRYPT_PRIMITIVES) - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_sec1_der(mbedtls_pk_uecc(*pk), key, keylen) == 0) { - return (0); - } -#else /* TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_ECP_C) - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), key, keylen) == 0) { - return (0); - } - mbedtls_pk_free(pk); -#endif /* MBEDTLS_ECP_C */ -#endif /* TINYCRYPT_PRIMITIVES */ - - /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, - * it is ok to leave the PK context initialized but not - * freed: It is the caller's responsibility to call pk_init() - * before calling this function, and to call pk_free() - * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C - * isn't, this leads to mbedtls_pk_free() being called - * twice, once here and once by the caller, but this is - * also ok and in line with the mbedtls_pk_free() calls - * on failed PEM parsing attempts. */ - - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); -} - -/* - * Parse a public key - */ -int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *p; -#if defined(MBEDTLS_RSA_C) - const mbedtls_pk_info_t *pk_info; -#endif -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; -#endif - - PK_VALIDATE_RET(ctx != NULL); - if (keylen == 0) - return (MBEDTLS_ERR_PK_KEY_INVALID_FORMAT); - PK_VALIDATE_RET(key != NULL || keylen == 0); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init(&pem); -#if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN RSA PUBLIC KEY-----", - "-----END RSA PUBLIC KEY-----", key, NULL, 0, - &len); - - if (ret == 0) { - p = pem.buf; - if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { - mbedtls_pem_free(&pem); - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - } - - if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { - mbedtls_pem_free(&pem); - return (ret); - } - - if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) - mbedtls_pk_free(ctx); - - mbedtls_pem_free(&pem); - return (ret); - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - return (ret); - } -#endif /* MBEDTLS_RSA_C */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = - mbedtls_pem_read_buffer(&pem, "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", key, NULL, 0, &len); - - if (ret == 0) { - /* - * Was PEM encoded - */ - p = pem.buf; - - ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); - mbedtls_pem_free(&pem); - return (ret); - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - return (ret); - } - mbedtls_pem_free(&pem); -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_RSA_C) - if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) - return (MBEDTLS_ERR_PK_UNKNOWN_PK_ALG); - - if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) - return (ret); - - p = (unsigned char *)key; - ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx)); - if (ret == 0) { - return (ret); - } - mbedtls_pk_free(ctx); - if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) { - return (ret); - } -#endif /* MBEDTLS_RSA_C */ - p = (unsigned char *)key; - - ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); - - return (ret); -} - -#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/pkwrite.c b/matter/mbedtls/tinycrypt/src/pkwrite.c deleted file mode 100644 index 6874744dee..0000000000 --- a/matter/mbedtls/tinycrypt/src/pkwrite.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Public Key layer for writing key files and structures - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_WRITE_C) - -#include "mbedtls/asn1write.h" -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/pk.h" -#include "mbedtls/platform_util.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/bignum.h" -#include "mbedtls/ecp.h" -#include "mbedtls/platform_util.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" -#include "psa/crypto.h" -#endif -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Parameter validation macros based on platform_util.h */ -#define PK_VALIDATE_RET(cond) \ - MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA) -#define PK_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond) - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, - mbedtls_rsa_context *rsa) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - mbedtls_mpi T; - - mbedtls_mpi_init(&T); - - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) - goto end_of_export; - len += ret; - -end_of_export: - - mbedtls_mpi_free(&T); - if (ret < 0) - return (ret); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return ((int)len); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(TINYCRYPT_PRIMITIVES) -static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, - mbedtls_pk_context const *key) { - size_t const len = 1 + 2 * NUM_ECC_BYTES; - mbedtls_uecc_keypair const *const uecc = mbedtls_pk_uecc(*key); - - if (*p < start || (size_t)(*p - start) < len) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - *p -= len; - (*p)[0] = 0x04; - mbedtls_platform_memcpy(*p + 1, uecc->public_key, 2 * NUM_ECC_BYTES); - - return ((int)len); -} - -/* - * privateKey OCTET STRING -- always of length ceil(log2(n)/8) - */ -static int pk_write_ec_privkey(unsigned char **p, unsigned char *start, - mbedtls_pk_context const *key) { - mbedtls_uecc_keypair const *const uecc = mbedtls_pk_uecc(*key); - return (mbedtls_asn1_write_octet_string(p, start, uecc->private_key, - NUM_ECC_BYTES)); -} - -/* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * } - */ -static int pk_write_ec_param(unsigned char **p, unsigned char *start, - mbedtls_pk_context const *key) { - int ret; - size_t len = 0; - const char *oid; - size_t oid_len; - ((void)key); - - if ((ret = mbedtls_oid_get_oid_by_ec_grp(MBEDTLS_UECC_DP_SECP256R1, &oid, - &oid_len)) != 0) - return (ret); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); - - return ((int)len); -} -#else /* TINYCRYPT_PRIMITIVES */ -#if defined(MBEDTLS_ECP_C) -/* - * EC public key is an EC point - */ -static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; - - if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, &len, - buf, sizeof(buf))) != 0) { - return (ret); - } - - if (*p < start || (size_t)(*p - start) < len) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - *p -= len; - memcpy(*p, buf, len); - - return ((int)len); -} - -/* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * } - */ -static int pk_write_ec_param(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - const char *oid; - size_t oid_len; - - if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) - return (ret); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); - - return ((int)len); -} - -/* - * privateKey OCTET STRING -- always of length ceil(log2(n)/8) - */ -static int pk_write_ec_private(unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t byte_length = (ec->grp.pbits + 7) / 8; - unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; - - ret = mbedtls_ecp_write_key(ec, tmp, byte_length); - if (ret != 0) - goto exit; - ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); - -exit: - mbedtls_platform_zeroize(tmp, byte_length); - return (ret); -} -#endif /* MBEDTLS_ECP_C */ -#endif /* TINYCRYPT_PRIMITIVES */ - -int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - - PK_VALIDATE_RET(p != NULL); - PK_VALIDATE_RET(*p != NULL); - PK_VALIDATE_RET(start != NULL); - PK_VALIDATE_RET(key != NULL); - -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) - MBEDTLS_ASN1_CHK_ADD(len, - pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key))); - else -#endif -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); -#else - MBEDTLS_ASN1_CHK_ADD(len, - pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key))); -#endif - else -#endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { - size_t buffer_size; - psa_key_id_t *key_id = (psa_key_id_t *)key->pk_ctx; - - if (*p < start) - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - - buffer_size = (size_t)(*p - start); - if (psa_export_public_key(*key_id, start, buffer_size, &len) != - PSA_SUCCESS) { - return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); - } else { - *p -= len; - memmove(*p, start, len); - } - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - return ((int)len); -} - -int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *key, unsigned char *buf, - size_t size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *c; - size_t len = 0, par_len = 0, oid_len; - mbedtls_pk_type_t pk_type; - const char *oid; - - PK_VALIDATE_RET(key != NULL); - if (size == 0) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - PK_VALIDATE_RET(buf != NULL); - - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); - - if (c - buf < 1) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ - *--c = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); - - pk_type = mbedtls_pk_get_type(key); -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) - if (pk_type == MBEDTLS_PK_ECKEY) { -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, key)); -#else - MBEDTLS_ASN1_CHK_ADD(par_len, - pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); -#endif - } -#endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (pk_type == MBEDTLS_PK_OPAQUE) { - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - psa_key_id_t key_id; - psa_ecc_family_t curve; - size_t bits; - - key_id = *((psa_key_id_t *)key->pk_ctx); - if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) - return (MBEDTLS_ERR_PK_HW_ACCEL_FAILED); - key_type = psa_get_key_type(&attributes); - bits = psa_get_key_bits(&attributes); - psa_reset_key_attributes(&attributes); - - curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type); - if (curve == 0) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits, &oid, &oid_len); - if (ret != 0) - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - /* Write EC algorithm parameters; that's akin - * to pk_write_ec_param() above. */ - MBEDTLS_ASN1_CHK_ADD(par_len, - mbedtls_asn1_write_oid(&c, buf, oid, oid_len)); - - /* The rest of the function works as for legacy EC contexts. */ - pk_type = MBEDTLS_PK_ECKEY; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len)) != 0) { - return (ret); - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier( - &c, buf, oid, oid_len, par_len)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return ((int)len); -} - -int mbedtls_pk_write_key_der(mbedtls_pk_context *key, unsigned char *buf, - size_t size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *c; - size_t len = 0; - - PK_VALIDATE_RET(key != NULL); - if (size == 0) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - PK_VALIDATE_RET(buf != NULL); - - c = buf + size; - -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - mbedtls_mpi T; /* Temporary holding the exported parameters */ - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key); - - /* - * Export the parameters one after another to avoid simultaneous copies. - */ - - mbedtls_mpi_init(&T); - - /* Export QP */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export DQ */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export DP */ - if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export Q */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export P */ - if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export D */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) - goto end_of_export; - len += ret; - - end_of_export: - - mbedtls_mpi_free(&T); - if (ret < 0) - return (ret); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag( - &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - mbedtls_pk_ec(*key); - size_t pub_len = 0, par_len = 0; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - - /* publicKey */ -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, key)); -#else - MBEDTLS_ASN1_CHK_ADD(pub_len, - pk_write_ec_pubkey(&c, buf, mbedtls_pk_ec(*key))); -#endif - - if (c - buf < 1) - return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); - *--c = 0; - pub_len += 1; - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD( - pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD( - pub_len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 1)); - len += pub_len; - - /* parameters */ -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, key)); -#else - MBEDTLS_ASN1_CHK_ADD(par_len, - pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); -#endif - - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len)); - MBEDTLS_ASN1_CHK_ADD( - par_len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)); - len += par_len; - - /* privateKey */ -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_privkey(&c, buf, key)); -#else - MBEDTLS_ASN1_CHK_ADD(len, - pk_write_ec_private(&c, buf, mbedtls_pk_ec(*key))); -#endif - - /* version */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag( - &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - } else -#endif /* MBEDTLS_ECP_C || TINYCRYPT_PRIMITIVES */ - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - return ((int)len); -} - -#if defined(MBEDTLS_PEM_WRITE_C) - -#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" -#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" - -#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" - -/* - * Max sizes of key per types. Shown as tag + len (+ content). - */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSA public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 9 (rsa oid) - * + 1 + 1 (params null) - * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) - * RSAPublicKey ::= SEQUENCE { 1 + 3 - * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 - * } - */ -#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) - -/* - * RSA private keys: - * RSAPrivateKey ::= SEQUENCE { 1 + 3 - * version Version, 1 + 1 + 1 - * modulus INTEGER, 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) - * } - */ -#define MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + MBEDTLS_MPI_MAX_SIZE % 2) -#define RSA_PRV_DER_MAX_BYTES \ - (47 + 3 * MBEDTLS_MPI_MAX_SIZE + 5 * MPI_MAX_SIZE_2) - -#else /* MBEDTLS_RSA_C */ - -#define RSA_PUB_DER_MAX_BYTES 0 -#define RSA_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 7 (ec oid) - * + 1 + 1 + 9 (namedCurve oid) - * subjectPublicKey BIT STRING 1 + 2 + 1 [1] - * + 1 (point format) [1] - * + 2 * ECP_MAX (coords) [1] - * } - */ -#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) - -/* - * EC private keys: - * ECPrivateKey ::= SEQUENCE { 1 + 2 - * version INTEGER , 1 + 1 + 1 - * privateKey OCTET STRING, 1 + 1 + ECP_MAX - * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) - * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above - * } - */ -#define ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_ECP_MAX_BYTES) - -#else /* MBEDTLS_ECP_C */ - -#if defined(TINYCRYPT_PRIMITIVES) - -/* see above, replacing ECP_MAX_BYTES with 32 (256-bit) */ -#define ECP_PUB_DER_MAX_BYTES 30 + 2 * 32 -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * 32 - -#else /* TINYCRYPT_PRIMITIVES */ - -#define ECP_PUB_DER_MAX_BYTES 0 -#define ECP_PRV_DER_MAX_BYTES 0 - -#endif /* TINYCRYPT_PRIMITIVES */ - -#endif /* MBEDTLS_ECP_C */ - -#define PUB_DER_MAX_BYTES \ - (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? RSA_PUB_DER_MAX_BYTES \ - : ECP_PUB_DER_MAX_BYTES) -#define PRV_DER_MAX_BYTES \ - (RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? RSA_PRV_DER_MAX_BYTES \ - : ECP_PRV_DER_MAX_BYTES) - -int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *key, unsigned char *buf, - size_t size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PUB_DER_MAX_BYTES]; - size_t olen = 0; - - PK_VALIDATE_RET(key != NULL); - PK_VALIDATE_RET(buf != NULL || size == 0); - - if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, sizeof(output_buf))) < - 0) { - return (ret); - } - - if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen)) != 0) { - return (ret); - } - - return (0); -} - -int mbedtls_pk_write_key_pem(mbedtls_pk_context *key, unsigned char *buf, - size_t size) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PRV_DER_MAX_BYTES]; - const char *begin, *end; - size_t olen = 0; - - PK_VALIDATE_RET(key != NULL); - PK_VALIDATE_RET(buf != NULL || size == 0); - - if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) - return (ret); - -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - begin = PEM_BEGIN_PRIVATE_KEY_RSA; - end = PEM_END_PRIVATE_KEY_RSA; - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) || defined(TINYCRYPT_PRIMITIVES) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - begin = PEM_BEGIN_PRIVATE_KEY_EC; - end = PEM_END_PRIVATE_KEY_EC; - } else -#endif /* MBEDTLS_ECP_C || TINYCRYPT_PRIMITIVES */ - return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); - - if ((ret = mbedtls_pem_write_buffer(begin, end, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen)) != 0) { - return (ret); - } - - return (0); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/matter/mbedtls/tinycrypt/src/platform_util.c b/matter/mbedtls/tinycrypt/src/platform_util.c deleted file mode 100644 index 1261619396..0000000000 --- a/matter/mbedtls/tinycrypt/src/platform_util.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Common and shared functions used by multiple modules in the Mbed TLS - * library. - * - * 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. - */ - -/* - * Ensure gmtime_r is available even with -std=c99; must be defined before - * config.h, which pulls in glibc's features.h. Harmless on other platforms. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 200112L -#endif - -#include "common.h" - -#include "mbedtls/platform.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/threading.h" - -#if defined(TINYCRYPT_PRIMITIVES) -#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) -#include "platform_fault.h" -#else -static void mbedtls_platform_fault() {} -#endif -#endif /* TINYCRYPT_PRIMITIVES */ - -#include -#include - -/* Max number of loops for mbedtls_platform_random_delay. */ -#define MAX_RAND_DELAY 100 - -/* Parameters for the linear congruential generator used as a non-cryptographic - * random number generator. The same parameters are used by e.g. ANSI C. */ -#define RAND_MULTIPLIER 1103515245 -#define RAND_INCREMENT 12345 -#define RAND_MODULUS 0x80000000 - -/* The number of iterations after which the seed of the non-cryptographic - * random number generator will be changed. This is used only if the - * MBEDTLS_ENTROPY_HARDWARE_ALT option is enabled. */ -#define RAND_SEED_LIFE 10000 - -#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) -/* - * This implementation should never be optimized out by the compiler - * - * This implementation for mbedtls_platform_zeroize() was inspired from Colin - * Percival's blog article at: - * - * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html - * - * It uses a volatile function pointer to the standard memset(). Because the - * pointer is volatile the compiler expects it to change at - * any time and will not optimize out the call that could potentially perform - * other operations on the input buffer instead of just setting it to 0. - * Nevertheless, as pointed out by davidtgoldblatt on Hacker News - * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for - * details), optimizations of the following form are still possible: - * - * if( memset_func != memset ) - * memset_func( buf, 0, len ); - * - * Note that it is extremely difficult to guarantee that - * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers - * in a portable way. For this reason, Mbed TLS also provides the configuration - * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure - * mbedtls_platform_zeroize() to use a suitable implementation for their - * platform and needs. - */ -#if defined(TINYCRYPT_PRIMITIVES) - -void *mbedtls_platform_memset(void *, int, size_t); -static void *(*const volatile memset_func)(void *, int, - size_t) = mbedtls_platform_memset; - -void *mbedtls_platform_zeroize(void *buf, size_t len) { - volatile size_t vlen = len; - - MBEDTLS_INTERNAL_VALIDATE_RET((len == 0 || buf != NULL), NULL); - - if (vlen > 0) { - return memset_func(buf, 0, vlen); - } else { - mbedtls_platform_random_delay(); - if (vlen == 0 && vlen == len) { - return buf; - } - } - return NULL; -} - -#else - -static void *(*const volatile memset_func)(void *, int, size_t) = memset; - -void mbedtls_platform_zeroize(void *buf, size_t len) { - MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL); - - if (len > 0) - memset_func(buf, 0, len); -} - -#endif /* TINYCRYPT_PRIMITIVES */ - -#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ - -#if defined(TINYCRYPT_PRIMITIVES) - -void *mbedtls_platform_memset(void *ptr, int value, size_t num) { - size_t i, start_offset = 0; - volatile size_t flow_counter = 0; - volatile char *b = ptr; - char rnd_data; - if (num > 0) { - start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); - - rnd_data = (char)mbedtls_platform_random_in_range(256); - - /* Perform a memset operations with random data and start from a random - * location */ - for (i = start_offset; i < num; ++i) { - b[i] = rnd_data; - flow_counter++; - } - - /* Start from a random location with target data */ - for (i = start_offset; i < num; ++i) { - b[i] = value; - flow_counter++; - } - - /* Second memset operation with random data */ - for (i = 0; i < start_offset; ++i) { - b[i] = rnd_data; - flow_counter++; - } - - /* Finish memset operation with correct data */ - for (i = 0; i < start_offset; ++i) { - b[i] = value; - flow_counter++; - } - } - /* check the correct number of iterations */ - if (flow_counter == 2 * num) { - mbedtls_platform_random_delay(); - if (flow_counter == 2 * num) { - return ptr; - } - } - mbedtls_platform_fault(); - return NULL; -} - -void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num) { - size_t i; - volatile size_t flow_counter = 0; - - if (num > 0) { - /* Randomize start offset. */ - size_t start_offset = - (size_t)mbedtls_platform_random_in_range((uint32_t)num); - /* Randomize initial data to prevent leakage while copying */ - uint32_t data = mbedtls_platform_random_in_range(256); - - /* Use memset with random value at first to increase security - memset is - not normally part of the memcpy function and here can be useed - with regular, unsecured implementation */ - memset((void *)dst, data, num); - - /* Make a copy starting from a random location. */ - i = start_offset; - do { - ((char *)dst)[i] = ((char *)src)[i]; - flow_counter++; - } while ((i = (i + 1) % num) != start_offset); - } - - /* check the correct number of iterations */ - if (flow_counter == num) { - mbedtls_platform_random_delay(); - if (flow_counter == num) { - return dst; - } - } - mbedtls_platform_fault(); - return NULL; -} - -int mbedtls_platform_memmove(void *dst, const void *src, size_t num) { - void *ret1 = NULL; - void *ret2 = NULL; - /* The buffers can have a common part, so we cannot do a copy from a random - * location. By using a temporary buffer we can do so, but the cost of it - * is using more memory and longer transfer time. */ - void *tmp = mbedtls_calloc(1, num); - if (tmp != NULL) { - ret1 = mbedtls_platform_memcpy(tmp, src, num); - ret2 = mbedtls_platform_memcpy(dst, tmp, num); - mbedtls_free(tmp); - if (ret1 == tmp && ret2 == dst) { - return 0; - } - return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; - } - - return MBEDTLS_ERR_PLATFORM_ALLOC_FAILED; -} - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_platform_memcmp(const void *buf1, const void *buf2, size_t num) { - return (mbedtls_platform_memequal(buf1, buf2, num)); -} -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num) { - volatile const unsigned char *A = (volatile const unsigned char *)buf1; - volatile const unsigned char *B = (volatile const unsigned char *)buf2; - volatile unsigned char diff = 0; - - /* Start from a random location and check the correct number of iterations */ - size_t i, flow_counter = 0; - size_t start_offset = 0; - if (num > 0) { - start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); - - for (i = start_offset; i < num; i++) { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } - - for (i = 0; i < start_offset; i++) { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } - } - /* Return 0 only when diff is 0 and flow_counter is equal to num */ - return ((int)diff | (int)(flow_counter ^ num)); -} - -/* This function implements a non-cryptographic random number generator based - * on the linear congruential generator algorithm. Additionally, if the - * MBEDTLS_ENTROPY_HARDWARE_ALT flag is defined, the seed is set at the first - * call of this function with using a hardware random number generator and - * changed every RAND_SEED_LIFE number of iterations. - * - * The value of the returned number is in the range [0; 0xffff]. - * - * Note: The range of values with a 16-bit precision is related to the modulo - * parameter of the generator and the fact that the function does not return the - * full value of the internal state of the generator. - */ -static uint32_t mbedtls_platform_random_uint16(void) { - /* Set random_state - the first random value should not be zero. */ - static uint32_t random_state = RAND_INCREMENT; - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - - static uint32_t random_seed_life = 0; - - if (0 < random_seed_life) { - --random_seed_life; - } else { - size_t olen = 0; - uint32_t hw_random; - mbedtls_hardware_poll(NULL, (unsigned char *)&hw_random, sizeof(hw_random), - &olen); - if (olen == sizeof(hw_random)) { - random_state ^= hw_random; - random_seed_life = RAND_SEED_LIFE; - } - } - -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ - - random_state = - ((random_state * RAND_MULTIPLIER) + RAND_INCREMENT) % RAND_MODULUS; - - /* Do not return the entire random_state to hide generator predictability for - * the next iteration */ - return ((random_state >> 15) & 0xffff); -} - -uint32_t mbedtls_platform_random_uint32(void) { - return ((mbedtls_platform_random_uint16() << 16) | - mbedtls_platform_random_uint16()); -} - -void mbedtls_platform_random_buf(uint8_t *buf, size_t len) { - volatile size_t flow_control = 0, flow_control_check = len; - uint16_t val; - - while (len > 1) { - val = mbedtls_platform_random_uint16(); - buf[len - 1] = (uint8_t)val; - buf[len - 2] = (uint8_t)(val >> 8); - len -= 2; - flow_control += 2; - } - if (len == 1) { - buf[0] = (uint8_t)mbedtls_platform_random_uint16(); - flow_control++; - } - - if (flow_control == flow_control_check) { - return; - } - mbedtls_platform_fault(); -} - -uint32_t mbedtls_platform_random_in_range(uint32_t num) { - return mbedtls_platform_random_uint32() % num; -} - -void mbedtls_platform_random_delay(void) { -#if defined(MBEDTLS_FI_COUNTERMEASURES) - uint32_t rn_1, rn_2, rn_3; - volatile size_t i = 0; - uint8_t shift; - - rn_1 = mbedtls_platform_random_in_range(MAX_RAND_DELAY); - rn_2 = mbedtls_platform_random_in_range(0xffffffff) + 1; - rn_3 = mbedtls_platform_random_in_range(0xffffffff) + 1; - - do { - i++; - /* Dummy calculations to increase the time between iterations and - * make side channel attack more difficult by reducing predictability - * of its behaviour. */ - shift = (rn_2 & 0x07) + 1; - if (i % 2) - rn_2 = (rn_2 >> shift) | (rn_2 << (32 - shift)); - else - rn_3 = (rn_3 << shift) | (rn_3 >> (32 - shift)); - rn_2 ^= rn_3; - } while (i < rn_1 || rn_2 == 0 || rn_3 == 0); - -#endif /* MBEDTLS_FI_COUNTERMEASURES */ - return; -} - -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) -#include -#if !defined(_WIN32) && \ - (defined(unix) || defined(__unix) || defined(__unix__) || \ - (defined(__APPLE__) && defined(__MACH__))) -#include -#endif /* !_WIN32 && (unix || __unix || __unix__ || \ - * (__APPLE__ && __MACH__)) */ - -#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \ - (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \ - _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L)) -/* - * This is a convenience shorthand macro to avoid checking the long - * preprocessor conditions above. Ideally, we could expose this macro in - * platform_util.h and simply use it in platform_util.c, threading.c and - * threading.h. However, this macro is not part of the Mbed TLS public API, so - * we keep it private by only defining it in this file - */ -#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) -#define PLATFORM_UTIL_USE_GMTIME -#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ - -#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ - ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ - _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ - -struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt, - struct tm *tm_buf) { -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - return ((gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL); -#elif !defined(PLATFORM_UTIL_USE_GMTIME) - return (gmtime_r(tt, tm_buf)); -#else - struct tm *lt; - -#if defined(MBEDTLS_THREADING_C) - if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) - return (NULL); -#endif /* MBEDTLS_THREADING_C */ - - lt = gmtime(tt); - - if (lt != NULL) { - memcpy(tm_buf, lt, sizeof(struct tm)); - } - -#if defined(MBEDTLS_THREADING_C) - if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) - return (NULL); -#endif /* MBEDTLS_THREADING_C */ - - return ((lt == NULL) ? NULL : tm_buf); -#endif /* _WIN32 && !EFIX64 && !EFI32 */ -} -#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/matter/mbedtls/tinycrypt/src/sha256.c b/matter/mbedtls/tinycrypt/src/sha256.c deleted file mode 100644 index b4efd20445..0000000000 --- a/matter/mbedtls/tinycrypt/src/sha256.c +++ /dev/null @@ -1,217 +0,0 @@ -/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static void compress(unsigned int *iv, const uint8_t *data); - -int tc_sha256_init(TCSha256State_t s) -{ - /* input sanity check: */ - if (s == (TCSha256State_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* - * Setting the initial state values. - * These values correspond to the first 32 bits of the fractional parts - * of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17 - * and 19. - */ - _set((uint8_t *) s, 0x00, sizeof(*s)); - s->iv[0] = 0x6a09e667; - s->iv[1] = 0xbb67ae85; - s->iv[2] = 0x3c6ef372; - s->iv[3] = 0xa54ff53a; - s->iv[4] = 0x510e527f; - s->iv[5] = 0x9b05688c; - s->iv[6] = 0x1f83d9ab; - s->iv[7] = 0x5be0cd19; - - return TC_CRYPTO_SUCCESS; -} - -int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen) -{ - /* input sanity check: */ - if (s == (TCSha256State_t) 0 || - data == (void *) 0) { - return TC_CRYPTO_FAIL; - } else if (datalen == 0) { - return TC_CRYPTO_SUCCESS; - } - - while (datalen-- > 0) { - s->leftover[s->leftover_offset++] = *(data++); - if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) { - compress(s->iv, s->leftover); - s->leftover_offset = 0; - s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3); - } - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_sha256_final(uint8_t *digest, TCSha256State_t s) -{ - unsigned int i; - - /* input sanity check: */ - if (digest == (uint8_t *) 0 || - s == (TCSha256State_t) 0) { - return TC_CRYPTO_FAIL; - } - - s->bits_hashed += (s->leftover_offset << 3); - - s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */ - if (s->leftover_offset > (sizeof(s->leftover) - 8)) { - /* there is not room for all the padding in this block */ - _set(s->leftover + s->leftover_offset, 0x00, - sizeof(s->leftover) - s->leftover_offset); - compress(s->iv, s->leftover); - s->leftover_offset = 0; - } - - /* add the padding and the length in big-Endian format */ - _set(s->leftover + s->leftover_offset, 0x00, - sizeof(s->leftover) - 8 - s->leftover_offset); - s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed); - s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8); - s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16); - s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24); - s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32); - s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40); - s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48); - s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56); - - /* hash the padding and length */ - compress(s->iv, s->leftover); - - /* copy the iv out to digest */ - for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) { - unsigned int t = *((unsigned int *) &s->iv[i]); - *digest++ = (uint8_t)(t >> 24); - *digest++ = (uint8_t)(t >> 16); - *digest++ = (uint8_t)(t >> 8); - *digest++ = (uint8_t)(t); - } - - /* destroy the current state */ - _set(s, 0, sizeof(*s)); - - return TC_CRYPTO_SUCCESS; -} - -/* - * Initializing SHA-256 Hash constant words K. - * These values correspond to the first 32 bits of the fractional parts of the - * cube roots of the first 64 primes between 2 and 311. - */ -static const unsigned int k256[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, - 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, - 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, - 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, - 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, - 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, - 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 -}; - -static inline unsigned int ROTR(unsigned int a, unsigned int n) -{ - return (((a) >> n) | ((a) << (32 - n))); -} - -#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22)) -#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25)) -#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3)) -#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10)) - -#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c))) -#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c))) - -static inline unsigned int BigEndian(const uint8_t **c) -{ - unsigned int n = 0; - - n = (((unsigned int)(*((*c)++))) << 24); - n |= ((unsigned int)(*((*c)++)) << 16); - n |= ((unsigned int)(*((*c)++)) << 8); - n |= ((unsigned int)(*((*c)++))); - return n; -} - -static void compress(unsigned int *iv, const uint8_t *data) -{ - unsigned int a, b, c, d, e, f, g, h; - unsigned int s0, s1; - unsigned int t1, t2; - unsigned int work_space[16]; - unsigned int n; - unsigned int i; - - a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3]; - e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7]; - - for (i = 0; i < 16; ++i) { - n = BigEndian(&data); - t1 = work_space[i] = n; - t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; - t2 = Sigma0(a) + Maj(a, b, c); - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - for ( ; i < 64; ++i) { - s0 = work_space[(i+1)&0x0f]; - s0 = sigma0(s0); - s1 = work_space[(i+14)&0x0f]; - s1 = sigma1(s1); - - t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf]; - t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i]; - t2 = Sigma0(a) + Maj(a, b, c); - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d; - iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h; -} diff --git a/matter/mbedtls/tinycrypt/src/tinycript_util.c b/matter/mbedtls/tinycrypt/src/tinycript_util.c new file mode 100644 index 0000000000..950191fb05 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/tinycript_util.c @@ -0,0 +1,206 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * 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. + */ + +// This files is not part of the tinycript librairy. It is used to define function tinycript requires that are not present in the Simplicity SDK mbedtls fork + +#include "mbedtls/platform_util.h" +#include + +#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) +#include "platform_fault.h" +#else +static void mbedtls_platform_fault() +{ +} +#endif + +/* Parameters for the linear congruential generator used as a non-cryptographic + * random number generator. The same parameters are used by e.g. ANSI C. */ +#define RAND_MULTIPLIER 1103515245 +#define RAND_INCREMENT 12345 +#define RAND_MODULUS 0x80000000 + +/* Max number of loops for mbedtls_platform_random_delay. */ +#define MAX_RAND_DELAY 100 + +/* This function implements a non-cryptographic random number generator based + * on the linear congruential generator algorithm. Additionally, if the + * MBEDTLS_ENTROPY_HARDWARE_ALT flag is defined, the seed is set at the first + * call of this function with using a hardware random number generator and + * changed every RAND_SEED_LIFE number of iterations. + * + * The value of the returned number is in the range [0; 0xffff]. + * + * Note: The range of values with a 16-bit precision is related to the modulo + * parameter of the generator and the fact that the function does not return the + * full value of the internal state of the generator. + */ +static uint32_t mbedtls_platform_random_uint16(void) +{ + /* Set random_state - the first random value should not be zero. */ + static uint32_t random_state = RAND_INCREMENT; +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + static uint32_t random_seed_life = 0; + if (0 < random_seed_life) { + --random_seed_life; + } else { + size_t olen = 0; + uint32_t hw_random; + mbedtls_hardware_poll(NULL, (unsigned char *)&hw_random, sizeof(hw_random), &olen); + if (olen == sizeof(hw_random)) { + random_state ^= hw_random; + random_seed_life = RAND_SEED_LIFE; + } + } +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + random_state = ((random_state * RAND_MULTIPLIER) + RAND_INCREMENT) % RAND_MODULUS; + /* Do not return the entire random_state to hide generator predictability for + * the next iteration */ + return ((random_state >> 15) & 0xffff); +} + +uint32_t mbedtls_platform_random_uint32(void) +{ + return ((mbedtls_platform_random_uint16() << 16) | mbedtls_platform_random_uint16()); +} + +uint32_t mbedtls_platform_random_in_range(uint32_t num) +{ + return mbedtls_platform_random_uint32() % num; +} + +void mbedtls_platform_random_delay(void) +{ +#if defined(MBEDTLS_FI_COUNTERMEASURES) + uint32_t rn_1, rn_2, rn_3; + volatile size_t i = 0; + uint8_t shift; + rn_1 = mbedtls_platform_random_in_range(MAX_RAND_DELAY); + rn_2 = mbedtls_platform_random_in_range(0xffffffff) + 1; + rn_3 = mbedtls_platform_random_in_range(0xffffffff) + 1; + do { + i++; + /* Dummy calculations to increase the time between iterations and + * make side channel attack more difficult by reducing predictability + * of its behaviour. */ + shift = (rn_2 & 0x07) + 1; + if (i % 2) + rn_2 = (rn_2 >> shift) | (rn_2 << (32 - shift)); + else + rn_3 = (rn_3 << shift) | (rn_3 >> (32 - shift)); + rn_2 ^= rn_3; + } while (i < rn_1 || rn_2 == 0 || rn_3 == 0); +#endif /* MBEDTLS_FI_COUNTERMEASURES */ + return; +} + +void mbedtls_platform_random_buf(uint8_t *buf, size_t len) +{ + volatile size_t flow_control = 0, flow_control_check = len; + uint16_t val; + while (len > 1) { + val = mbedtls_platform_random_uint16(); + buf[len - 1] = (uint8_t)val; + buf[len - 2] = (uint8_t)(val >> 8); + len -= 2; + flow_control += 2; + } + if (len == 1) { + buf[0] = (uint8_t)mbedtls_platform_random_uint16(); + flow_control++; + } + if (flow_control == flow_control_check) { + return; + } + mbedtls_platform_fault(); +} + +void *mbedtls_platform_memset(void *ptr, int value, size_t num) +{ + size_t i, start_offset = 0; + volatile size_t flow_counter = 0; + volatile char *b = ptr; + char rnd_data; + if (num > 0) { + start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); + rnd_data = (char)mbedtls_platform_random_in_range(256); + /* Perform a memset operations with random data and start from a random + * location */ + for (i = start_offset; i < num; ++i) { + b[i] = rnd_data; + flow_counter++; + } + /* Start from a random location with target data */ + for (i = start_offset; i < num; ++i) { + b[i] = value; + flow_counter++; + } + /* Second memset operation with random data */ + for (i = 0; i < start_offset; ++i) { + b[i] = rnd_data; + flow_counter++; + } + /* Finish memset operation with correct data */ + for (i = 0; i < start_offset; ++i) { + b[i] = value; + flow_counter++; + } + } + /* check the correct number of iterations */ + if (flow_counter == 2 * num) { + mbedtls_platform_random_delay(); + if (flow_counter == 2 * num) { + return ptr; + } + } + mbedtls_platform_fault(); + return NULL; +} + +void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num) +{ + size_t i; + volatile size_t flow_counter = 0; + if (num > 0) { + /* Randomize start offset. */ + size_t start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); + /* Randomize initial data to prevent leakage while copying */ + uint32_t data = mbedtls_platform_random_in_range(256); + /* Use memset with random value at first to increase security - memset is + not normally part of the memcpy function and here can be useed + with regular, unsecured implementation */ + memset((void *)dst, data, num); + /* Make a copy starting from a random location. */ + i = start_offset; + do { + ((char *)dst)[i] = ((char *)src)[i]; + flow_counter++; + } while ((i = (i + 1) % num) != start_offset); + } + /* check the correct number of iterations */ + if (flow_counter == num) { + mbedtls_platform_random_delay(); + if (flow_counter == num) { + return dst; + } + } + mbedtls_platform_fault(); + return NULL; +} \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/x509_crt.c b/matter/mbedtls/tinycrypt/src/x509_crt.c deleted file mode 100644 index 0e4016cdc8..0000000000 --- a/matter/mbedtls/tinycrypt/src/x509_crt.c +++ /dev/null @@ -1,3196 +0,0 @@ -/* - * X.509 certificate parsing and verification - * - * 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. - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - * - * [SIRO] - * https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/x509_crt.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" -#include "psa/crypto.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif -#endif - -#if defined(MBEDTLS_FS_IO) -#include -#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) -#include -#include -#include -#include -#endif /* !_WIN32 || EFIX64 || EFI32 */ -#endif - -/* - * Item in a verification chain: cert and flags for it - */ -typedef struct { - mbedtls_x509_crt *crt; - uint32_t flags; -} x509_crt_verify_chain_item; - -/* - * Max size of verification chain: end-entity + intermediates + trusted root - */ -#define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) - -/* Default profile. Do not remove items unless there are serious security - * concerns. */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = { - /* Only SHA-2 hashes */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 2048, -}; - -/* - * Next-default profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = { - /* Hashes from SHA-256 and above */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), - 0xFFFFFFF, /* Any PK alg */ -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_X509_ID_FLAG(MBEDTLS_UECC_DP_SECP256R1), -#elif defined(MBEDTLS_ECP_C) - /* Curves at or above 128-bit security level */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1), -#else - 0, -#endif - 2048, -}; - -/* - * NSA Suite B Profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = { - /* Only SHA-256 and 384 */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384), - /* Only ECDSA */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), -#if defined(TINYCRYPT_PRIMITIVES) - MBEDTLS_X509_ID_FLAG(MBEDTLS_UECC_DP_SECP256R1), -#elif defined(MBEDTLS_ECP_C) - /* Only NIST P-256 and P-384 */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), -#else - 0, -#endif - 0, -}; - -/* - * Check md_alg against profile - * Return 0 if md_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg) { - if (md_alg == MBEDTLS_MD_NONE) - return (-1); - - if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) - return (0); - - return (-1); -} - -/* - * Check pk_alg against profile - * Return 0 if pk_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg) { - if (pk_alg == MBEDTLS_PK_NONE) - return (-1); - - if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) - return (0); - - return (-1); -} - -/* - * Check key against profile - * Return 0 if pk is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, - const mbedtls_pk_context *pk) { - const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk); - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) { - if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) - return (0); - - return (-1); - } -#endif - -#if defined(TINYCRYPT_PRIMITIVES) - if (pk_alg == MBEDTLS_PK_ECKEY) { - if ((profile->allowed_curves & MBEDTLS_UECC_DP_SECP256R1) != 0) - return (0); - - return (-1); - } -#endif /* TINYCRYPT_PRIMITIVES */ - -#if defined(MBEDTLS_ECP_C) - if (pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || - pk_alg == MBEDTLS_PK_ECKEY_DH) { - const mbedtls_ecp_group_id gid = mbedtls_pk_ec(*pk)->grp.id; - - if (gid == MBEDTLS_ECP_DP_NONE) - return (-1); - - if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) - return (0); - - return (-1); - } -#endif - - return (-1); -} - -/* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp(const void *s1, const void *s2, size_t len) { - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for (i = 0; i < len; i++) { - diff = n1[i] ^ n2[i]; - - if (diff == 0) - continue; - - if (diff == 32 && - ((n1[i] >= 'a' && n1[i] <= 'z') || (n1[i] >= 'A' && n1[i] <= 'Z'))) { - continue; - } - - return (-1); - } - - return (0); -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name) { - size_t i; - size_t cn_idx = 0, cn_len = strlen(cn); - - /* We can't have a match if there is no wildcard to match */ - if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') - return (-1); - - for (i = 0; i < cn_len; ++i) { - if (cn[i] == '.') { - cn_idx = i; - break; - } - } - - if (cn_idx == 0) - return (-1); - - if (cn_len - cn_idx == name->len - 1 && - x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) { - return (0); - } - - return (-1); -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp(const mbedtls_x509_buf *a, - const mbedtls_x509_buf *b) { - if (a->tag == b->tag && a->len == b->len && memcmp(a->p, b->p, b->len) == 0) { - return (0); - } - - if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || - a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && - (b->tag == MBEDTLS_ASN1_UTF8_STRING || - b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && - a->len == b->len && x509_memcasecmp(a->p, b->p, b->len) == 0) { - return (0); - } - - return (-1); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp(const mbedtls_x509_name *a, - const mbedtls_x509_name *b) { - /* Avoid recursion, it might not be optimised by the compiler */ - while (a != NULL || b != NULL) { - if (a == NULL || b == NULL) - return (-1); - - /* type */ - if (a->oid.tag != b->oid.tag || a->oid.len != b->oid.len || - memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) { - return (-1); - } - - /* value */ - if (x509_string_cmp(&a->val, &b->val) != 0) - return (-1); - - /* structure of the list of sets */ - if (a->next_merged != b->next_merged) - return (-1); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return (0); -} - -/* - * Reset (init or clear) a verify_chain - */ -static void -x509_crt_verify_chain_reset(mbedtls_x509_crt_verify_chain *ver_chain) { - size_t i; - - for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) { - ver_chain->items[i].crt = NULL; - ver_chain->items[i].flags = (uint32_t)-1; - } - - ver_chain->len = 0; - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - ver_chain->trust_ca_cb_result = NULL; -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -} - -/* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ -static int x509_get_version(unsigned char **p, const unsigned char *end, - int *ver) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - *ver = 0; - return (0); - } - - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret)); - } - - end = *p + len; - - if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret)); - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} - -/* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ -static int x509_get_dates(unsigned char **p, const unsigned char *end, - mbedtls_x509_time *from, mbedtls_x509_time *to) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret)); - - end = *p + len; - - if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) - return (ret); - - if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) - return (ret); - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} - -/* - * X.509 v2/v3 unique identifier (not parsed) - */ -static int x509_get_uid(unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *uid, int n) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (*p == end) - return (0); - - uid->tag = **p; - - if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | n)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) - return (0); - - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret)); - } - - uid->p = *p; - *p += uid->len; - - return (0); -} - -static int x509_get_basic_constraints(unsigned char **p, - const unsigned char *end, int *ca_istrue, - int *max_pathlen) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - *ca_istrue = 0; /* DEFAULT FALSE */ - *max_pathlen = 0; /* endless */ - - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (*p == end) - return (0); - - if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) - ret = mbedtls_asn1_get_int(p, end, ca_istrue); - - if (ret != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (*ca_istrue != 0) - *ca_istrue = 1; - } - - if (*p == end) - return (0); - - if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer - * overflow, which is an undefined behavior. */ - if (*max_pathlen == INT_MAX) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH)); - - (*max_pathlen)++; - - return (0); -} - -static int x509_get_ns_cert_type(unsigned char **p, const unsigned char *end, - unsigned char *ns_cert_type) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_bitstring bs = {0, 0, NULL}; - - if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (bs.len != 1) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH)); - - /* Get actual bitstring */ - *ns_cert_type = *bs.p; - return (0); -} - -static int x509_get_key_usage(unsigned char **p, const unsigned char *end, - unsigned int *key_usage) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t i; - mbedtls_x509_bitstring bs = {0, 0, NULL}; - - if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (bs.len < 1) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH)); - - /* Get actual bitstring */ - *key_usage = 0; - for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) { - *key_usage |= (unsigned int)bs.p[i] << (8 * i); - } - - return (0); -} - -/* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - * - * KeyPurposeId ::= OBJECT IDENTIFIER - */ -static int x509_get_ext_key_usage(unsigned char **p, const unsigned char *end, - mbedtls_x509_sequence *ext_key_usage) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, - MBEDTLS_ASN1_OID)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - /* Sequence length must be >= 1 */ - if (ext_key_usage->buf.p == NULL) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH)); - - return (0); -} - -/* - * SubjectAltName ::= GeneralNames - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - * - * NOTE: we list all types, but only use dNSName and otherName - * of type HwModuleName, as defined in RFC 4108, at this point. - */ -static int x509_get_subject_alt_name(unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *subject_alt_name) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len, tag_len; - mbedtls_asn1_buf *buf; - unsigned char tag; - mbedtls_asn1_sequence *cur = subject_alt_name; - - /* Get main sequence tag */ - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (*p + len != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - while (*p < end) { - mbedtls_x509_subject_alternative_name dummy_san_buf; - memset(&dummy_san_buf, 0, sizeof(dummy_san_buf)); - - tag = **p; - (*p)++; - if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if ((tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != MBEDTLS_ASN1_CONTEXT_SPECIFIC) { - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)); - } - - /* - * Check that the SAN is structured correctly. - */ - ret = mbedtls_x509_parse_subject_alt_name(&(cur->buf), &dummy_san_buf); - /* - * In case the extension is malformed, return an error, - * and clear the allocated sequences. - */ - if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - mbedtls_x509_sequence *seq_cur = subject_alt_name->next; - mbedtls_x509_sequence *seq_prv; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - subject_alt_name->next = NULL; - return (ret); - } - - /* Allocate and assign next pointer */ - if (cur->buf.p != NULL) { - if (cur->next != NULL) - return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS); - - cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); - - if (cur->next == NULL) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_ALLOC_FAILED)); - - cur = cur->next; - } - - buf = &(cur->buf); - buf->tag = tag; - buf->p = *p; - buf->len = tag_len; - *p += buf->len; - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} - -/* - * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } - * - * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } - * - * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - * - * PolicyInformation ::= SEQUENCE { - * policyIdentifier CertPolicyId, - * policyQualifiers SEQUENCE SIZE (1..MAX) OF - * PolicyQualifierInfo OPTIONAL } - * - * CertPolicyId ::= OBJECT IDENTIFIER - * - * PolicyQualifierInfo ::= SEQUENCE { - * policyQualifierId PolicyQualifierId, - * qualifier ANY DEFINED BY policyQualifierId } - * - * -- policyQualifierIds for Internet policy qualifiers - * - * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } - * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } - * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } - * - * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) - * - * Qualifier ::= CHOICE { - * cPSuri CPSuri, - * userNotice UserNotice } - * - * CPSuri ::= IA5String - * - * UserNotice ::= SEQUENCE { - * noticeRef NoticeReference OPTIONAL, - * explicitText DisplayText OPTIONAL } - * - * NoticeReference ::= SEQUENCE { - * organization DisplayText, - * noticeNumbers SEQUENCE OF INTEGER } - * - * DisplayText ::= CHOICE { - * ia5String IA5String (SIZE (1..200)), - * visibleString VisibleString (SIZE (1..200)), - * bmpString BMPString (SIZE (1..200)), - * utf8String UTF8String (SIZE (1..200)) } - * - * NOTE: we only parse and use anyPolicy without qualifiers at this point - * as defined in RFC 5280. - */ -static int -x509_get_certificate_policies(unsigned char **p, const unsigned char *end, - mbedtls_x509_sequence *certificate_policies) { - int ret, parse_ret = 0; - size_t len; - mbedtls_asn1_buf *buf; - mbedtls_asn1_sequence *cur = certificate_policies; - - /* Get main sequence tag */ - ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); - if (ret != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if (*p + len != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* - * Cannot be an empty sequence. - */ - if (len == 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - while (*p < end) { - mbedtls_x509_buf policy_oid; - const unsigned char *policy_end; - - /* - * Get the policy sequence - */ - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - policy_end = *p + len; - - if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, MBEDTLS_ASN1_OID)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - policy_oid.tag = MBEDTLS_ASN1_OID; - policy_oid.len = len; - policy_oid.p = *p; - - /* - * Only AnyPolicy is currently supported when enforcing policy. - */ - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { - /* - * Set the parsing return code but continue parsing, in case this - * extension is critical and - * MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION is configured. - */ - parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } - - /* Allocate and assign next pointer */ - if (cur->buf.p != NULL) { - if (cur->next != NULL) - return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS); - - cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); - - if (cur->next == NULL) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_ALLOC_FAILED)); - - cur = cur->next; - } - - buf = &(cur->buf); - buf->tag = policy_oid.tag; - buf->p = policy_oid.p; - buf->len = policy_oid.len; - - *p += len; - - /* - * If there is an optional qualifier, then *p < policy_end - * Check the Qualifier len to verify it doesn't exceed policy_end. - */ - if (*p < policy_end) { - if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - /* - * Skip the optional policy qualifiers. - */ - *p += len; - } - - if (*p != policy_end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (parse_ret); -} - -/* - * X.509 v3 extensions - * - */ -static int x509_get_crt_ext(unsigned char **p, const unsigned char *end, - mbedtls_x509_crt *crt, mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; - - if (*p == end) - return (0); - - if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) - return (ret); - - end = crt->v3_ext.p + crt->v3_ext.len; - while (*p < end) { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - mbedtls_x509_buf extn_oid = {0, 0, NULL}; - int is_critical = 0; /* DEFAULT FALSE */ - int ext_type = 0; - - if ((ret = mbedtls_asn1_get_tag( - p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - end_ext_data = *p + len; - - /* Get extension ID */ - if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, - MBEDTLS_ASN1_OID)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - extn_oid.tag = MBEDTLS_ASN1_OID; - extn_oid.p = *p; - *p += extn_oid.len; - - /* Get optional critical */ - if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && - (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - /* Data should be octet string type */ - if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - start_ext_octet = *p; - end_ext_octet = *p + len; - - if (end_ext_octet != end_ext_data) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - /* - * Detect supported extensions - */ - ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); - - if (ret != 0) { - /* Give the callback (if any) a chance to handle the extension */ - if (cb != NULL) { - ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet); - if (ret != 0 && is_critical) - return (ret); - *p = end_ext_octet; - continue; - } - - /* No parser found, skip extension */ - *p = end_ext_octet; - -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if (is_critical) { - /* Data is marked as critical: fail */ - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)); - } -#endif - continue; - } - - /* Forbid repeated extensions */ - if ((crt->ext_types & ext_type) != 0) - return (MBEDTLS_ERR_X509_INVALID_EXTENSIONS); - - crt->ext_types |= ext_type; - - switch (ext_type) { - case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: - /* Parse basic constraints */ - if ((ret = x509_get_basic_constraints(p, end_ext_octet, &crt->ca_istrue, - &crt->max_pathlen)) != 0) - return (ret); - break; - - case MBEDTLS_X509_EXT_KEY_USAGE: - /* Parse key usage */ - if ((ret = x509_get_key_usage(p, end_ext_octet, &crt->key_usage)) != 0) - return (ret); - break; - - case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: - /* Parse extended key usage */ - if ((ret = x509_get_ext_key_usage(p, end_ext_octet, - &crt->ext_key_usage)) != 0) - return (ret); - break; - - case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: - /* Parse subject alt name */ - if ((ret = x509_get_subject_alt_name(p, end_ext_octet, - &crt->subject_alt_names)) != 0) - return (ret); - break; - - case MBEDTLS_X509_EXT_NS_CERT_TYPE: - /* Parse netscape certificate type */ - if ((ret = x509_get_ns_cert_type(p, end_ext_octet, &crt->ns_cert_type)) != - 0) - return (ret); - break; - - case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: - /* Parse certificate policies type */ - if ((ret = x509_get_certificate_policies( - p, end_ext_octet, &crt->certificate_policies)) != 0) { - /* Give the callback (if any) a chance to handle the extension - * if it contains unsupported policies */ - if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && - cb(p_ctx, crt, &extn_oid, is_critical, start_ext_octet, - end_ext_octet) == 0) - break; - -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if (is_critical) - return (ret); - else -#endif - /* - * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we - * cannot interpret or enforce the policy. However, it is up to - * the user to choose how to enforce the policies, - * unless the extension is critical. - */ - if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) - return (ret); - } - break; - - default: - /* - * If this is a non-critical extension, which the oid layer - * supports, but there isn't an x509 parser for it, - * skip the extension. - */ -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if (is_critical) - return (MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE); - else -#endif - *p = end_ext_octet; - } - } - - if (*p != end) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - - return (0); -} - -/* - * Parse and fill a single X.509 certificate in DER format - */ -static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, - const unsigned char *buf, size_t buflen, - int make_copy, mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - unsigned char *p, *end, *crt_end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - - memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); - memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); - memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); - - /* - * Check for valid input - */ - if (crt == NULL || buf == NULL) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - /* Use the original buffer until we figure out actual length. */ - p = (unsigned char *)buf; - len = buflen; - end = p + len; - - /* - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERR_X509_INVALID_FORMAT); - } - - end = crt_end = p + len; - crt->raw.len = crt_end - buf; - if (make_copy != 0) { - /* Create and populate a new buffer for the raw field. */ - crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); - if (crt->raw.p == NULL) - return (MBEDTLS_ERR_X509_ALLOC_FAILED); - - memcpy(crt->raw.p, buf, crt->raw.len); - crt->own_buffer = 1; - - p += crt->raw.len - len; - end = crt_end = p + len; - } else { - crt->raw.p = (unsigned char *)buf; - crt->own_buffer = 0; - } - - /* - * TBSCertificate ::= SEQUENCE { - */ - crt->tbs.p = p; - - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret)); - } - - end = p + len; - crt->tbs.len = end - crt->tbs.p; - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * signature AlgorithmIdentifier - */ - if ((ret = x509_get_version(&p, end, &crt->version)) != 0 || - (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 || - (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid, &sig_params1)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - if (crt->version < 0 || crt->version > 2) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERR_X509_UNKNOWN_VERSION); - } - - crt->version++; - - if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1, &crt->sig_md, - &crt->sig_pk, &crt->sig_opts)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - /* - * issuer Name - */ - crt->issuer_raw.p = p; - - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret)); - } - - if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - crt->issuer_raw.len = p - crt->issuer_raw.p; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - * - */ - if ((ret = x509_get_dates(&p, end, &crt->valid_from, &crt->valid_to)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - /* - * subject Name - */ - crt->subject_raw.p = p; - - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret)); - } - - if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - crt->subject_raw.len = p - crt->subject_raw.p; - - /* - * SubjectPublicKeyInfo - */ - crt->pk_raw.p = p; - if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - crt->pk_raw.len = p - crt->pk_raw.p; - - /* - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - */ - if (crt->version == 2 || crt->version == 3) { - ret = x509_get_uid(&p, end, &crt->issuer_id, 1); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - } - - if (crt->version == 2 || crt->version == 3) { - ret = x509_get_uid(&p, end, &crt->subject_id, 2); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - } - -#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - if (crt->version == 3) -#endif - { - ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - } - - if (p != end) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - - end = crt_end; - - /* - * } - * -- end of TBSCertificate - * - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - if (crt->sig_oid.len != sig_oid2.len || - memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 || - sig_params1.tag != sig_params2.tag || - sig_params1.len != sig_params2.len || - (sig_params1.len != 0 && - memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERR_X509_SIG_MISMATCH); - } - - if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) { - mbedtls_x509_crt_free(crt); - return (ret); - } - - if (p != end) { - mbedtls_x509_crt_free(crt); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - - return (0); -} - -/* - * Parse one X.509 certificate in DER format from a buffer and add them to a - * chained list - */ -static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen, int make_copy, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *crt = chain, *prev = NULL; - - /* - * Check for valid input - */ - if (crt == NULL || buf == NULL) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - while (crt->version != 0 && crt->next != NULL) { - prev = crt; - crt = crt->next; - } - - /* - * Add new certificate on the end of the chain if needed. - */ - if (crt->version != 0 && crt->next == NULL) { - crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); - - if (crt->next == NULL) - return (MBEDTLS_ERR_X509_ALLOC_FAILED); - - prev = crt; - mbedtls_x509_crt_init(crt->next); - crt = crt->next; - } - - ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx); - if (ret != 0) { - if (prev) - prev->next = NULL; - - if (crt != chain) - mbedtls_free(crt); - - return (ret); - } - - return (0); -} - -int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, - const unsigned char *buf, size_t buflen) { - return ( - mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL)); -} - -int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen, int make_copy, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) { - return (mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, - p_ctx)); -} - -int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, - const unsigned char *buf, size_t buflen) { - return ( - mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL)); -} - -/* - * Parse one or more PEM certificates from a buffer and add them to the chained - * list - */ -int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen) { -#if defined(MBEDTLS_PEM_PARSE_C) - int success = 0, first_error = 0, total_failed = 0; - int buf_format = MBEDTLS_X509_FORMAT_DER; -#endif - - /* - * Check for valid input - */ - if (chain == NULL || buf == NULL) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - /* - * Determine buffer content. Buffer contains either one DER certificate or - * one or more PEM certificates. - */ -#if defined(MBEDTLS_PEM_PARSE_C) - if (buflen != 0 && buf[buflen - 1] == '\0' && - strstr((const char *)buf, "-----BEGIN CERTIFICATE-----") != NULL) { - buf_format = MBEDTLS_X509_FORMAT_PEM; - } - - if (buf_format == MBEDTLS_X509_FORMAT_DER) - return mbedtls_x509_crt_parse_der(chain, buf, buflen); -#else - return mbedtls_x509_crt_parse_der(chain, buf, buflen); -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) - if (buf_format == MBEDTLS_X509_FORMAT_PEM) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_pem_context pem; - - /* 1 rather than 0 since the terminating NULL byte is counted in */ - while (buflen > 1) { - size_t use_len; - mbedtls_pem_init(&pem); - - /* If we get there, we know the string is null-terminated */ - ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN CERTIFICATE-----", - "-----END CERTIFICATE-----", buf, NULL, 0, - &use_len); - - if (ret == 0) { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) { - return (ret); - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - - /* - * PEM header and footer were found - */ - buflen -= use_len; - buf += use_len; - - if (first_error == 0) - first_error = ret; - - total_failed++; - continue; - } else - break; - - ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen); - - mbedtls_pem_free(&pem); - - if (ret != 0) { - /* - * Quit parsing on a memory error - */ - if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) - return (ret); - - if (first_error == 0) - first_error = ret; - - total_failed++; - continue; - } - - success = 1; - } - } - - if (success) - return (total_failed); - else if (first_error) - return (first_error); - else - return (MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT); -#endif /* MBEDTLS_PEM_PARSE_C */ -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more certificates and add them to the chained list - */ -int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) - return (ret); - - ret = mbedtls_x509_crt_parse(chain, buf, n); - - mbedtls_platform_zeroize(buf, n); - mbedtls_free(buf); - - return (ret); -} - -int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) { - int ret = 0; -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - int w_ret; - WCHAR szDir[MAX_PATH]; - char filename[MAX_PATH]; - char *p; - size_t len = strlen(path); - - WIN32_FIND_DATAW file_data; - HANDLE hFind; - - if (len > MAX_PATH - 3) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - memset(szDir, 0, sizeof(szDir)); - memset(filename, 0, MAX_PATH); - memcpy(filename, path, len); - filename[len++] = '\\'; - p = filename + len; - filename[len++] = '*'; - - w_ret = - MultiByteToWideChar(CP_ACP, 0, filename, (int)len, szDir, MAX_PATH - 3); - if (w_ret == 0) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - hFind = FindFirstFileW(szDir, &file_data); - if (hFind == INVALID_HANDLE_VALUE) - return (MBEDTLS_ERR_X509_FILE_IO_ERROR); - - len = MAX_PATH - len; - do { - memset(p, 0, len); - - if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - continue; - - w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, - lstrlenW(file_data.cFileName), p, (int)len - 1, - NULL, NULL); - if (w_ret == 0) { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - - w_ret = mbedtls_x509_crt_parse_file(chain, filename); - if (w_ret < 0) - ret++; - else - ret += w_ret; - } while (FindNextFileW(hFind, &file_data) != 0); - - if (GetLastError() != ERROR_NO_MORE_FILES) - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - -cleanup: - FindClose(hFind); -#else /* _WIN32 */ - int t_ret; - int snp_ret; - struct stat sb; - struct dirent *entry; - char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; - DIR *dir = opendir(path); - - if (dir == NULL) - return (MBEDTLS_ERR_X509_FILE_IO_ERROR); - -#if defined(MBEDTLS_THREADING_C) - if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) { - closedir(dir); - return (ret); - } -#endif /* MBEDTLS_THREADING_C */ - - memset(&sb, 0, sizeof(sb)); - - while ((entry = readdir(dir)) != NULL) { - snp_ret = mbedtls_snprintf(entry_name, sizeof entry_name, "%s/%s", path, - entry->d_name); - - if (snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name) { - ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - goto cleanup; - } else if (stat(entry_name, &sb) == -1) { - if (errno == ENOENT) { - /* Broken symbolic link - ignore this entry. - stat(2) will return this error for either (a) a dangling - symlink or (b) a missing file. - Given that we have just obtained the filename from readdir, - assume that it does exist and therefore treat this as a - dangling symlink. */ - continue; - } else { - /* Some other file error; report the error. */ - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - } - - if (!S_ISREG(sb.st_mode)) - continue; - - // Ignore parse errors - // - t_ret = mbedtls_x509_crt_parse_file(chain, entry_name); - if (t_ret < 0) - ret++; - else - ret += t_ret; - } - -cleanup: - closedir(dir); - -#if defined(MBEDTLS_THREADING_C) - if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) - ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; -#endif /* MBEDTLS_THREADING_C */ - -#endif /* _WIN32 */ - - return (ret); -} -#endif /* MBEDTLS_FS_IO */ - -/* - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * HardwareModuleName ::= SEQUENCE { - * hwType OBJECT IDENTIFIER, - * hwSerialNum OCTET STRING } - * - * NOTE: we currently only parse and use otherName of type HwModuleName, - * as defined in RFC 4108. - */ -static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name, - mbedtls_x509_san_other_name *other_name) { - int ret = 0; - size_t len; - unsigned char *p = subject_alt_name->p; - const unsigned char *end = p + subject_alt_name->len; - mbedtls_x509_buf cur_oid; - - if ((subject_alt_name->tag & - (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) != - (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) { - /* - * The given subject alternative name is not of type "othername". - */ - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - cur_oid.tag = MBEDTLS_ASN1_OID; - cur_oid.p = p; - cur_oid.len = len; - - /* - * Only HwModuleName is currently supported. - */ - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) { - return (MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE); - } - - if (p + len >= end) { - mbedtls_platform_zeroize(other_name, sizeof(*other_name)); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - p += len; - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if ((ret = mbedtls_asn1_get_tag( - &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; - other_name->value.hardware_module_name.oid.p = p; - other_name->value.hardware_module_name.oid.len = len; - - if (p + len >= end) { - mbedtls_platform_zeroize(other_name, sizeof(*other_name)); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - p += len; - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != - 0) - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret)); - - other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; - other_name->value.hardware_module_name.val.p = p; - other_name->value.hardware_module_name.val.len = len; - p += len; - if (p != end) { - mbedtls_platform_zeroize(other_name, sizeof(*other_name)); - return (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH)); - } - return (0); -} - -static int -x509_info_subject_alt_name(char **buf, size_t *size, - const mbedtls_x509_sequence *subject_alt_name, - const char *prefix) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = subject_alt_name; - mbedtls_x509_subject_alternative_name san; - int parse_ret; - - while (cur != NULL) { - memset(&san, 0, sizeof(san)); - parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san); - if (parse_ret != 0) { - if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } else { - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } - cur = cur->next; - continue; - } - - switch (san.type) { - /* - * otherName - */ - case MBEDTLS_X509_SAN_OTHER_NAME: { - mbedtls_x509_san_other_name *other_name = &san.san.other_name; - - ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, - &other_name->value.hardware_module_name.oid) != 0) { - ret = mbedtls_snprintf(p, n, - "\n%s hardware module name :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_snprintf( - p, n, "\n%s hardware type : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_oid_get_numeric_string( - p, n, &other_name->value.hardware_module_name.oid); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( - p, n, "\n%s hardware serial number : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if (other_name->value.hardware_module_name.val.len >= n) { - *p = '\0'; - return (MBEDTLS_ERR_X509_BUFFER_TOO_SMALL); - } - - memcpy(p, other_name->value.hardware_module_name.val.p, - other_name->value.hardware_module_name.val.len); - p += other_name->value.hardware_module_name.val.len; - - n -= other_name->value.hardware_module_name.val.len; - - } /* MBEDTLS_OID_ON_HW_MODULE_NAME */ - } break; - - /* - * dNSName - */ - case MBEDTLS_X509_SAN_DNS_NAME: { - ret = mbedtls_snprintf(p, n, "\n%s dNSName : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - if (san.san.unstructured_name.len >= n) { - *p = '\0'; - return (MBEDTLS_ERR_X509_BUFFER_TOO_SMALL); - } - - memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len); - p += san.san.unstructured_name.len; - n -= san.san.unstructured_name.len; - } break; - - /* - * Type not supported, skip item. - */ - default: - ret = mbedtls_snprintf(p, n, "\n%s ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - break; - } - - cur = cur->next; - } - - *p = '\0'; - - *size = n; - *buf = p; - - return (0); -} - -int mbedtls_x509_parse_subject_alt_name( - const mbedtls_x509_buf *san_buf, - mbedtls_x509_subject_alternative_name *san) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - switch (san_buf->tag & - (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) { - /* - * otherName - */ - case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME): { - mbedtls_x509_san_other_name other_name; - - ret = x509_get_other_name(san_buf, &other_name); - if (ret != 0) - return (ret); - - memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); - san->type = MBEDTLS_X509_SAN_OTHER_NAME; - memcpy(&san->san.other_name, &other_name, sizeof(other_name)); - - } break; - - /* - * dNSName - */ - case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME): { - memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name)); - san->type = MBEDTLS_X509_SAN_DNS_NAME; - - memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf)); - - } break; - - /* - * Type not supported - */ - default: - return (MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE); - } - return (0); -} - -#define PRINT_ITEM(i) \ - { \ - ret = mbedtls_snprintf(p, n, "%s" i, sep); \ - MBEDTLS_X509_SAFE_SNPRINTF; \ - sep = ", "; \ - } - -#define CERT_TYPE(type, name) \ - if (ns_cert_type & (type)) \ - PRINT_ITEM(name); - -static int x509_info_cert_type(char **buf, size_t *size, - unsigned char ns_cert_type) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA"); - CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA"); - - *size = n; - *buf = p; - - return (0); -} - -#define KEY_USAGE(code, name) \ - if (key_usage & (code)) \ - PRINT_ITEM(name); - -static int x509_info_key_usage(char **buf, size_t *size, - unsigned int key_usage) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature"); - KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment"); - KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement"); - KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign"); - KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign"); - KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only"); - KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only"); - - *size = n; - *buf = p; - - return (0); -} - -static int -x509_info_ext_key_usage(char **buf, size_t *size, - const mbedtls_x509_sequence *extended_key_usage) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = extended_key_usage; - const char *sep = ""; - - while (cur != NULL) { - if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) - desc = "???"; - - ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return (0); -} - -static int -x509_info_cert_policies(char **buf, size_t *size, - const mbedtls_x509_sequence *certificate_policies) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = certificate_policies; - const char *sep = ""; - - while (cur != NULL) { - if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) - desc = "???"; - - ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return (0); -} - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 18 -#define BC "18" -int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - if (NULL == crt) { - ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n"); - MBEDTLS_X509_SAFE_SNPRINTF; - - return ((int)(size - n)); - } - - ret = mbedtls_snprintf(p, n, "%scert. version : %d\n", prefix, - crt->version); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_snprintf(p, n, "%sserial number : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets(p, n, &crt->serial); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets(p, n, &crt->issuer); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets(p, n, &crt->subject); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, - "\n%sissued on : " - "%04d-%02d-%02d %02d:%02d:%02d", - prefix, crt->valid_from.year, crt->valid_from.mon, - crt->valid_from.day, crt->valid_from.hour, - crt->valid_from.min, crt->valid_from.sec); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, - "\n%sexpires on : " - "%04d-%02d-%02d %02d:%02d:%02d", - prefix, crt->valid_to.year, crt->valid_to.mon, - crt->valid_to.day, crt->valid_to.hour, - crt->valid_to.min, crt->valid_to.sec); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk, crt->sig_md, - crt->sig_opts); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* Key size */ - if ((ret = mbedtls_x509_key_size_helper( - key_size_str, BEFORE_COLON, mbedtls_pk_get_name(&crt->pk))) != 0) { - return (ret); - } - - ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, - (int)mbedtls_pk_get_bitlen(&crt->pk)); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* - * Optional extensions - */ - - if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) { - ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix, - crt->ca_istrue ? "true" : "false"); - MBEDTLS_X509_SAFE_SNPRINTF; - - if (crt->max_pathlen > 0) { - ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1); - MBEDTLS_X509_SAFE_SNPRINTF; - } - } - - if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { - ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_subject_alt_name(&p, &n, &crt->subject_alt_names, - prefix)) != 0) - return (ret); - } - - if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { - ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) - return (ret); - } - - if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { - ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_key_usage(&p, &n, crt->key_usage)) != 0) - return (ret); - } - - if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) { - ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_ext_key_usage(&p, &n, &crt->ext_key_usage)) != 0) - return (ret); - } - - if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) { - ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_cert_policies(&p, &n, &crt->certificate_policies)) != - 0) - return (ret); - } - - ret = mbedtls_snprintf(p, n, "\n"); - MBEDTLS_X509_SAFE_SNPRINTF; - - return ((int)(size - n)); -} - -struct x509_crt_verify_string { - int code; - const char *string; -}; - -static const struct x509_crt_verify_string x509_crt_verify_strings[] = { - {MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired"}, - {MBEDTLS_X509_BADCERT_REVOKED, - "The certificate has been revoked (is on a CRL)"}, - {MBEDTLS_X509_BADCERT_CN_MISMATCH, - "The certificate Common Name (CN) does not match with the expected CN"}, - {MBEDTLS_X509_BADCERT_NOT_TRUSTED, - "The certificate is not correctly signed by the trusted CA"}, - {MBEDTLS_X509_BADCRL_NOT_TRUSTED, - "The CRL is not correctly signed by the trusted CA"}, - {MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired"}, - {MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing"}, - {MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped"}, - {MBEDTLS_X509_BADCERT_OTHER, - "Other reason (can be used by verify callback)"}, - {MBEDTLS_X509_BADCERT_FUTURE, - "The certificate validity starts in the future"}, - {MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future"}, - {MBEDTLS_X509_BADCERT_KEY_USAGE, - "Usage does not match the keyUsage extension"}, - {MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, - "Usage does not match the extendedKeyUsage extension"}, - {MBEDTLS_X509_BADCERT_NS_CERT_TYPE, - "Usage does not match the nsCertType extension"}, - {MBEDTLS_X509_BADCERT_BAD_MD, - "The certificate is signed with an unacceptable hash."}, - {MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an " - "unacceptable PK alg (eg RSA vs ECDSA)."}, - {MBEDTLS_X509_BADCERT_BAD_KEY, - "The certificate is signed with an unacceptable key (eg bad curve, RSA " - "too short)."}, - {MBEDTLS_X509_BADCRL_BAD_MD, - "The CRL is signed with an unacceptable hash."}, - {MBEDTLS_X509_BADCRL_BAD_PK, - "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)."}, - {MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key " - "(eg bad curve, RSA too short)."}, - {0, NULL}}; - -int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, - uint32_t flags) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const struct x509_crt_verify_string *cur; - char *p = buf; - size_t n = size; - - for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) { - if ((flags & cur->code) == 0) - continue; - - ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string); - MBEDTLS_X509_SAFE_SNPRINTF; - flags ^= cur->code; - } - - if (flags != 0) { - ret = mbedtls_snprintf(p, n, - "%sUnknown reason " - "(this should not happen)\n", - prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return ((int)(size - n)); -} - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) -int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, - unsigned int usage) { - unsigned int usage_must, usage_may; - unsigned int may_mask = - MBEDTLS_X509_KU_ENCIPHER_ONLY | MBEDTLS_X509_KU_DECIPHER_ONLY; - - if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) - return (0); - - usage_must = usage & ~may_mask; - - if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - usage_may = usage & may_mask; - - if (((crt->key_usage & may_mask) | usage_may) != usage_may) - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); - - return (0); -} -#endif - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) -int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len) { - const mbedtls_x509_sequence *cur; - - /* Extension is not mandatory, absent means no restriction */ - if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) - return (0); - - /* - * Look for the requested usage (or wildcard ANY) in our list - */ - for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) { - const mbedtls_x509_buf *cur_oid = &cur->buf; - - if (cur_oid->len == usage_len && - memcmp(cur_oid->p, usage_oid, usage_len) == 0) { - return (0); - } - - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) - return (0); - } - - return (MBEDTLS_ERR_X509_BAD_INPUT_DATA); -} -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/* - * Return 1 if the certificate is revoked, or 0 otherwise. - */ -int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, - const mbedtls_x509_crl *crl) { - const mbedtls_x509_crl_entry *cur = &crl->entry; - - while (cur != NULL && cur->serial.len != 0) { - if (crt->serial.len == cur->serial.len && - memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) { - return (1); - } - - cur = cur->next; - } - - return (0); -} - -/* - * Check that the given certificate is not revoked according to the CRL. - * Skip validation if no CRL for the given CA is present. - */ -static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, - mbedtls_x509_crl *crl_list, - const mbedtls_x509_crt_profile *profile) { - int flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - - if (ca == NULL) - return (flags); - - while (crl_list != NULL) { - if (crl_list->version == 0 || - x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) { - crl_list = crl_list->next; - continue; - } - - /* - * Check if the CA is configured to sign CRLs - */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if (mbedtls_x509_crt_check_key_usage(ca, MBEDTLS_X509_KU_CRL_SIGN) != 0) { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } -#endif - - /* - * Check if CRL is correctly signed by the trusted CA - */ - if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) - flags |= MBEDTLS_X509_BADCRL_BAD_MD; - - if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) - flags |= MBEDTLS_X509_BADCRL_BAD_PK; - - md_info = mbedtls_md_info_from_type(crl_list->sig_md); - if (mbedtls_md(md_info, crl_list->tbs.p, crl_list->tbs.len, hash) != 0) { - /* Note: this can't happen except after an internal error */ - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - if (x509_profile_check_key(profile, &ca->pk) != 0) - flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, - crl_list->sig_md, hash, - mbedtls_md_get_size(md_info), crl_list->sig.p, - crl_list->sig.len) != 0) { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - /* - * Check for validity of CRL (Do not drop out) - */ - if (mbedtls_x509_time_is_past(&crl_list->next_update)) - flags |= MBEDTLS_X509_BADCRL_EXPIRED; - - if (mbedtls_x509_time_is_future(&crl_list->this_update)) - flags |= MBEDTLS_X509_BADCRL_FUTURE; - - /* - * Check if certificate is revoked - */ - if (mbedtls_x509_crt_is_revoked(crt, crl_list)) { - flags |= MBEDTLS_X509_BADCERT_REVOKED; - break; - } - - crl_list = crl_list->next; - } - - return (flags); -} -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/* - * Check the signature of a certificate by its parent - */ -static int x509_crt_check_signature(const mbedtls_x509_crt *child, - mbedtls_x509_crt *parent, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - size_t hash_len; -#if !defined(MBEDTLS_USE_PSA_CRYPTO) - const mbedtls_md_info_t *md_info; - md_info = mbedtls_md_info_from_type(child->sig_md); - hash_len = mbedtls_md_get_size(md_info); - - /* Note: hash errors can happen only after an internal error */ - if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) - return (-1); -#else - psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; - psa_algorithm_t hash_alg = mbedtls_psa_translate_md(child->sig_md); - - if (psa_hash_setup(&hash_operation, hash_alg) != PSA_SUCCESS) - return (-1); - - if (psa_hash_update(&hash_operation, child->tbs.p, child->tbs.len) != - PSA_SUCCESS) { - return (-1); - } - - if (psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_len) != - PSA_SUCCESS) { - return (-1); - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* Skip expensive computation on obvious mismatch */ - if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) - return (-1); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) { - return (mbedtls_pk_verify_restartable(&parent->pk, child->sig_md, hash, - hash_len, child->sig.p, - child->sig.len, &rs_ctx->pk)); - } -#else - (void)rs_ctx; -#endif - - return (mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, hash_len, child->sig.p, - child->sig.len)); -} - -/* - * Check if 'parent' is a suitable parent (signing CA) for 'child'. - * Return 0 if yes, -1 if not. - * - * top means parent is a locally-trusted certificate - */ -static int x509_crt_check_parent(const mbedtls_x509_crt *child, - const mbedtls_x509_crt *parent, int top) { - int need_ca_bit; - - /* Parent must be the issuer */ - if (x509_name_cmp(&child->issuer, &parent->subject) != 0) - return (-1); - - /* Parent must have the basicConstraints CA bit set as a general rule */ - need_ca_bit = 1; - - /* Exception: v1/v2 certificates that are locally trusted. */ - if (top && parent->version < 3) - need_ca_bit = 0; - - if (need_ca_bit && !parent->ca_istrue) - return (-1); - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if (need_ca_bit && mbedtls_x509_crt_check_key_usage( - parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { - return (-1); - } -#endif - - return (0); -} - -/* - * Find a suitable parent for child in candidates, or return NULL. - * - * Here suitable is defined as: - * 1. subject name matches child's issuer - * 2. if necessary, the CA bit is set and key usage allows signing certs - * 3. for trusted roots, the signature is correct - * (for intermediates, the signature is checked and the result reported) - * 4. pathlen constraints are satisfied - * - * If there's a suitable candidate which is also time-valid, return the first - * such. Otherwise, return the first suitable candidate (or NULL if there is - * none). - * - * The rationale for this rule is that someone could have a list of trusted - * roots with two versions on the same root with different validity periods. - * (At least one user reported having such a list and wanted it to just work.) - * The reason we don't just require time-validity is that generally there is - * only one version, and if it's expired we want the flags to state that - * rather than NOT_TRUSTED, as would be the case if we required it here. - * - * The rationale for rule 3 (signature for trusted roots) is that users might - * have two versions of the same CA with different keys in their list, and the - * way we select the correct one is by checking the signature (as we don't - * rely on key identifier extensions). (This is one way users might choose to - * handle key rollover, another relies on self-issued certs, see [SIRO].) - * - * Arguments: - * - [in] child: certificate for which we're looking for a parent - * - [in] candidates: chained list of potential parents - * - [out] r_parent: parent found (or NULL) - * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 - * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top - * of the chain, 0 otherwise - * - [in] path_cnt: number of intermediates seen so far - * - [in] self_cnt: number of self-signed intermediates seen so far - * (will never be greater than path_cnt) - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - 0 on success - * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise - */ -static int x509_crt_find_parent_in(mbedtls_x509_crt *child, - mbedtls_x509_crt *candidates, - mbedtls_x509_crt **r_parent, - int *r_signature_is_good, int top, - unsigned path_cnt, unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *parent, *fallback_parent; - int signature_is_good = 0, fallback_signature_is_good; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* did we have something in progress? */ - if (rs_ctx != NULL && rs_ctx->parent != NULL) { - /* restore saved state */ - parent = rs_ctx->parent; - fallback_parent = rs_ctx->fallback_parent; - fallback_signature_is_good = rs_ctx->fallback_signature_is_good; - - /* clear saved state */ - rs_ctx->parent = NULL; - rs_ctx->fallback_parent = NULL; - rs_ctx->fallback_signature_is_good = 0; - - /* resume where we left */ - goto check_signature; - } -#endif - - fallback_parent = NULL; - fallback_signature_is_good = 0; - - for (parent = candidates; parent != NULL; parent = parent->next) { - /* basic parenting skills (name, CA bit, key usage) */ - if (x509_crt_check_parent(child, parent, top) != 0) - continue; - - /* +1 because stored max_pathlen is 1 higher that the actual value */ - if (parent->max_pathlen > 0 && - (size_t)parent->max_pathlen < 1 + path_cnt - self_cnt) { - continue; - } - - /* Signature */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - check_signature: -#endif - ret = x509_crt_check_signature(child, parent, rs_ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->parent = parent; - rs_ctx->fallback_parent = fallback_parent; - rs_ctx->fallback_signature_is_good = fallback_signature_is_good; - - return (ret); - } -#else - (void)ret; -#endif - - signature_is_good = ret == 0; - if (top && !signature_is_good) - continue; - - /* optional time check */ - if (mbedtls_x509_time_is_past(&parent->valid_to) || - mbedtls_x509_time_is_future(&parent->valid_from)) { - if (fallback_parent == NULL) { - fallback_parent = parent; - fallback_signature_is_good = signature_is_good; - } - - continue; - } - - *r_parent = parent; - *r_signature_is_good = signature_is_good; - - break; - } - - if (parent == NULL) { - *r_parent = fallback_parent; - *r_signature_is_good = fallback_signature_is_good; - } - - return (0); -} - -/* - * Find a parent in trusted CAs or the provided chain, or return NULL. - * - * Searches in trusted CAs first, and return the first suitable parent found - * (see find_parent_in() for definition of suitable). - * - * Arguments: - * - [in] child: certificate for which we're looking for a parent, followed - * by a chain of possible intermediates - * - [in] trust_ca: list of locally trusted certificates - * - [out] parent: parent found (or NULL) - * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 - * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 - * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) - * - [in] self_cnt: number of self-signed certs in the chain so far - * (will always be no greater than path_cnt) - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - 0 on success - * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise - */ -static int x509_crt_find_parent(mbedtls_x509_crt *child, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crt **parent, - int *parent_is_trusted, int *signature_is_good, - unsigned path_cnt, unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *search_list; - - *parent_is_trusted = 1; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* restore then clear saved state if we have some stored */ - if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) { - *parent_is_trusted = rs_ctx->parent_is_trusted; - rs_ctx->parent_is_trusted = -1; - } -#endif - - while (1) { - search_list = *parent_is_trusted ? trust_ca : child->next; - - ret = - x509_crt_find_parent_in(child, search_list, parent, signature_is_good, - *parent_is_trusted, path_cnt, self_cnt, rs_ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->parent_is_trusted = *parent_is_trusted; - return (ret); - } -#else - (void)ret; -#endif - - /* stop here if found or already in second iteration */ - if (*parent != NULL || *parent_is_trusted == 0) - break; - - /* prepare second iteration */ - *parent_is_trusted = 0; - } - - /* extra precaution against mistakes in the caller */ - if (*parent == NULL) { - *parent_is_trusted = 0; - *signature_is_good = 0; - } - - return (0); -} - -/* - * Check if an end-entity certificate is locally trusted - * - * Currently we require such certificates to be self-signed (actually only - * check for self-issued as self-signatures are not checked) - */ -static int x509_crt_check_ee_locally_trusted(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca) { - mbedtls_x509_crt *cur; - - /* must be self-issued */ - if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) - return (-1); - - /* look for an exact match with trusted cert */ - for (cur = trust_ca; cur != NULL; cur = cur->next) { - if (crt->raw.len == cur->raw.len && - memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) { - return (0); - } - } - - /* too bad */ - return (-1); -} - -/* - * Build and verify a certificate chain - * - * Given a peer-provided list of certificates EE, C1, ..., Cn and - * a list of trusted certs R1, ... Rp, try to build and verify a chain - * EE, Ci1, ... Ciq [, Rj] - * such that every cert in the chain is a child of the next one, - * jumping to a trusted root as early as possible. - * - * Verify that chain and return it with flags for all issues found. - * - * Special cases: - * - EE == Rj -> return a one-element list containing it - * - EE, Ci1, ..., Ciq cannot be continued with a trusted root - * -> return that chain with NOT_TRUSTED set on Ciq - * - * Tests for (aspects of) this function should include at least: - * - trusted EE - * - EE -> trusted root - * - EE -> intermediate CA -> trusted root - * - if relevant: EE untrusted - * - if relevant: EE -> intermediate, untrusted - * with the aspect under test checked at each relevant level (EE, int, root). - * For some aspects longer chains are required, but usually length 2 is - * enough (but length 1 is not in general). - * - * Arguments: - * - [in] crt: the cert list EE, C1, ..., Cn - * - [in] trust_ca: the trusted list R1, ..., Rp - * - [in] ca_crl, profile: as in verify_with_profile() - * - [out] ver_chain: the built and verified chain - * Only valid when return value is 0, may contain garbage otherwise! - * Restart note: need not be the same when calling again to resume. - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - non-zero if the chain could not be fully built and examined - * - 0 is the chain was successfully built and examined, - * even if it was found to be invalid - */ -static int x509_crt_verify_chain(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - mbedtls_x509_crt_ca_cb_t f_ca_cb, - void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, - mbedtls_x509_crt_verify_chain *ver_chain, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - /* Don't initialize any of those variables here, so that the compiler can - * catch potential issues with jumping ahead when restarting */ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint32_t *flags; - mbedtls_x509_crt_verify_chain_item *cur; - mbedtls_x509_crt *child; - mbedtls_x509_crt *parent; - int parent_is_trusted; - int child_is_trusted; - int signature_is_good; - unsigned self_cnt; - mbedtls_x509_crt *cur_trust_ca = NULL; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* resume if we had an operation in progress */ - if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) { - /* restore saved state */ - *ver_chain = rs_ctx->ver_chain; /* struct copy */ - self_cnt = rs_ctx->self_cnt; - - /* restore derived state */ - cur = &ver_chain->items[ver_chain->len - 1]; - child = cur->crt; - flags = &cur->flags; - - goto find_parent; - } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - child = crt; - self_cnt = 0; - parent_is_trusted = 0; - child_is_trusted = 0; - - while (1) { - /* Add certificate to the verification chain */ - cur = &ver_chain->items[ver_chain->len]; - cur->crt = child; - cur->flags = 0; - ver_chain->len++; - flags = &cur->flags; - - /* Check time-validity (all certificates) */ - if (mbedtls_x509_time_is_past(&child->valid_to)) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if (mbedtls_x509_time_is_future(&child->valid_from)) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - /* Stop here for trusted roots (but not for trusted EE certs) */ - if (child_is_trusted) - return (0); - - /* Check signature algorithm: MD & PK algs */ - if (x509_profile_check_md_alg(profile, child->sig_md) != 0) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - /* Special case: EE certs that are locally trusted */ - if (ver_chain->len == 1 && - x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) { - return (0); - } - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - find_parent: -#endif - - /* Obtain list of potential trusted signers from CA callback, - * or use statically provided list. */ -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - if (f_ca_cb != NULL) { - mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result); - mbedtls_free(ver_chain->trust_ca_cb_result); - ver_chain->trust_ca_cb_result = NULL; - - ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result); - if (ret != 0) - return (MBEDTLS_ERR_X509_FATAL_ERROR); - - cur_trust_ca = ver_chain->trust_ca_cb_result; - } else -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - { - ((void)f_ca_cb); - ((void)p_ca_cb); - cur_trust_ca = trust_ca; - } - - /* Look for a parent in trusted CAs or up the chain */ - ret = x509_crt_find_parent(child, cur_trust_ca, &parent, &parent_is_trusted, - &signature_is_good, ver_chain->len - 1, self_cnt, - rs_ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->in_progress = x509_crt_rs_find_parent; - rs_ctx->self_cnt = self_cnt; - rs_ctx->ver_chain = *ver_chain; /* struct copy */ - - return (ret); - } -#else - (void)ret; -#endif - - /* No parent? We're done here */ - if (parent == NULL) { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - return (0); - } - - /* Count intermediate self-issued (not necessarily self-signed) certs. - * These can occur with some strategies for key rollover, see [SIRO], - * and should be excluded from max_pathlen checks. */ - if (ver_chain->len != 1 && - x509_name_cmp(&child->issuer, &child->subject) == 0) { - self_cnt++; - } - - /* path_cnt is 0 for the first intermediate CA, - * and if parent is trusted it's not an intermediate CA */ - if (!parent_is_trusted && - ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) { - /* return immediately to avoid overflow the chain array */ - return (MBEDTLS_ERR_X509_FATAL_ERROR); - } - - /* signature was checked while searching parent */ - if (!signature_is_good) - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - /* check size of signing key */ - if (x509_profile_check_key(profile, &parent->pk) != 0) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile); -#else - (void)ca_crl; -#endif - - /* prepare for next iteration */ - child = parent; - parent = NULL; - child_is_trusted = parent_is_trusted; - signature_is_good = 0; - } -} - -/* - * Check for CN match - */ -static int x509_crt_check_cn(const mbedtls_x509_buf *name, const char *cn, - size_t cn_len) { - /* try exact match */ - if (name->len == cn_len && x509_memcasecmp(cn, name->p, cn_len) == 0) { - return (0); - } - - /* try wildcard match */ - if (x509_check_wildcard(cn, name) == 0) { - return (0); - } - - return (-1); -} - -/* - * Check for SAN match, see RFC 5280 Section 4.2.1.6 - */ -static int x509_crt_check_san(const mbedtls_x509_buf *name, const char *cn, - size_t cn_len) { - const unsigned char san_type = - (unsigned char)name->tag & MBEDTLS_ASN1_TAG_VALUE_MASK; - - /* dNSName */ - if (san_type == MBEDTLS_X509_SAN_DNS_NAME) - return (x509_crt_check_cn(name, cn, cn_len)); - - /* (We may handle other types here later.) */ - - /* Unrecognized type */ - return (-1); -} - -/* - * Verify the requested CN - only call this if cn is not NULL! - */ -static void x509_crt_verify_name(const mbedtls_x509_crt *crt, const char *cn, - uint32_t *flags) { - const mbedtls_x509_name *name; - const mbedtls_x509_sequence *cur; - size_t cn_len = strlen(cn); - - if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { - for (cur = &crt->subject_alt_names; cur != NULL; cur = cur->next) { - if (x509_crt_check_san(&cur->buf, cn, cn_len) == 0) - break; - } - - if (cur == NULL) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } else { - for (name = &crt->subject; name != NULL; name = name->next) { - if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && - x509_crt_check_cn(&name->val, cn, cn_len) == 0) { - break; - } - } - - if (name == NULL) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } -} - -/* - * Merge the flags for all certs in the chain, after calling callback - */ -static int x509_crt_merge_flags_with_cb( - uint32_t *flags, const mbedtls_x509_crt_verify_chain *ver_chain, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned i; - uint32_t cur_flags; - const mbedtls_x509_crt_verify_chain_item *cur; - - for (i = ver_chain->len; i != 0; --i) { - cur = &ver_chain->items[i - 1]; - cur_flags = cur->flags; - - if (NULL != f_vrfy) - if ((ret = f_vrfy(p_vrfy, cur->crt, (int)i - 1, &cur_flags)) != 0) - return (ret); - - *flags |= cur_flags; - } - - return (0); -} - -/* - * Verify the certificate validity, with profile, restartable version - * - * This function: - * - checks the requested CN (if any) - * - checks the type and size of the EE cert's key, - * as that isn't done as part of chain building/verification currently - * - builds and verifies the chain - * - then calls the callback and merges the flags - * - * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` - * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the - * verification routine to search for trusted signers, and CRLs will - * be disabled. Otherwise, `trust_ca` will be used as the static list - * of trusted signers, and `ca_crl` will be use as the static list - * of CRLs. - */ -static int x509_crt_verify_restartable_ca_cb( - mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_pk_type_t pk_type; - mbedtls_x509_crt_verify_chain ver_chain; - uint32_t ee_flags; - - *flags = 0; - ee_flags = 0; - x509_crt_verify_chain_reset(&ver_chain); - - if (profile == NULL) { - ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; - goto exit; - } - - /* check name if requested */ - if (cn != NULL) - x509_crt_verify_name(crt, cn, &ee_flags); - - /* Check the type and size of the key */ - pk_type = mbedtls_pk_get_type(&crt->pk); - - if (x509_profile_check_pk_alg(profile, pk_type) != 0) - ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - if (x509_profile_check_key(profile, &crt->pk) != 0) - ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - /* Check the chain */ - ret = x509_crt_verify_chain(crt, trust_ca, ca_crl, f_ca_cb, p_ca_cb, profile, - &ver_chain, rs_ctx); - - if (ret != 0) - goto exit; - - /* Merge end-entity flags */ - ver_chain.items[0].flags |= ee_flags; - - /* Build final flags, calling callback on the way if any */ - ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy); - -exit: - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result); - mbedtls_free(ver_chain.trust_ca_cb_result); - ver_chain.trust_ca_cb_result = NULL; -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) - mbedtls_x509_crt_restart_free(rs_ctx); -#endif - - /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by - * the SSL module for authmode optional, but non-zero return from the - * callback means a fatal error so it shouldn't be ignored */ - if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) - ret = MBEDTLS_ERR_X509_FATAL_ERROR; - - if (ret != 0) { - *flags = (uint32_t)-1; - return (ret); - } - - if (*flags != 0) - return (MBEDTLS_ERR_X509_CERT_VERIFY_FAILED); - - return (0); -} - -/* - * Verify the certificate validity (default profile, not restartable) - */ -int mbedtls_x509_crt_verify( - mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { - return (x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, - &mbedtls_x509_crt_profile_default, - cn, flags, f_vrfy, p_vrfy, NULL)); -} - -/* - * Verify the certificate validity (user-chosen profile, not restartable) - */ -int mbedtls_x509_crt_verify_with_profile( - mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { - return (x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, - profile, cn, flags, f_vrfy, p_vrfy, - NULL)); -} - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -/* - * Verify the certificate validity (user-chosen profile, CA callback, - * not restartable). - */ -int mbedtls_x509_crt_verify_with_ca_cb( - mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy) { - return (x509_crt_verify_restartable_ca_cb(crt, NULL, NULL, f_ca_cb, p_ca_cb, - profile, cn, flags, f_vrfy, p_vrfy, - NULL)); -} -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - -int mbedtls_x509_crt_verify_restartable( - mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy, - mbedtls_x509_crt_restart_ctx *rs_ctx) { - return (x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, NULL, NULL, - profile, cn, flags, f_vrfy, p_vrfy, - rs_ctx)); -} - -/* - * Initialize a certificate chain - */ -void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) { - memset(crt, 0, sizeof(mbedtls_x509_crt)); -} - -/* - * Unallocate all certificate data - */ -void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) { - mbedtls_x509_crt *cert_cur = crt; - mbedtls_x509_crt *cert_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_sequence *seq_cur; - mbedtls_x509_sequence *seq_prv; - - if (crt == NULL) - return; - - do { - mbedtls_pk_free(&cert_cur->pk); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free(cert_cur->sig_opts); -#endif - - name_cur = cert_cur->issuer.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } - - name_cur = cert_cur->subject.next; - while (name_cur != NULL) { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name)); - mbedtls_free(name_prv); - } - - seq_cur = cert_cur->ext_key_usage.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - - seq_cur = cert_cur->subject_alt_names.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - - seq_cur = cert_cur->certificate_policies.next; - while (seq_cur != NULL) { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_platform_zeroize(seq_prv, sizeof(mbedtls_x509_sequence)); - mbedtls_free(seq_prv); - } - - if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { - mbedtls_platform_zeroize(cert_cur->raw.p, cert_cur->raw.len); - mbedtls_free(cert_cur->raw.p); - } - - cert_cur = cert_cur->next; - } while (cert_cur != NULL); - - cert_cur = crt; - do { - cert_prv = cert_cur; - cert_cur = cert_cur->next; - - mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt)); - if (cert_prv != crt) - mbedtls_free(cert_prv); - } while (cert_cur != NULL); -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Initialize a restart context - */ -void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx) { - mbedtls_pk_restart_init(&ctx->pk); - - ctx->parent = NULL; - ctx->fallback_parent = NULL; - ctx->fallback_signature_is_good = 0; - - ctx->parent_is_trusted = -1; - - ctx->in_progress = x509_crt_rs_none; - ctx->self_cnt = 0; - x509_crt_verify_chain_reset(&ctx->ver_chain); -} - -/* - * Free the components of a restart context - */ -void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) { - if (ctx == NULL) - return; - - mbedtls_pk_restart_free(&ctx->pk); - mbedtls_x509_crt_restart_init(ctx); -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/x509write_csr.c b/matter/mbedtls/tinycrypt/src/x509write_csr.c deleted file mode 100644 index 55443888a1..0000000000 --- a/matter/mbedtls/tinycrypt/src/x509write_csr.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * X.509 Certificate Signing Request writing - * - * 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. - */ -/* - * References: - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#if defined(MBEDTLS_X509_CSR_WRITE_C) - -#include "mbedtls/asn1write.h" -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/x509_csr.h" - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "mbedtls/psa_util.h" -#include "psa/crypto.h" -#endif - -#include -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) { - memset(ctx, 0, sizeof(mbedtls_x509write_csr)); -} - -void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) { - mbedtls_asn1_free_named_data_list(&ctx->subject); - mbedtls_asn1_free_named_data_list(&ctx->extensions); - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); -} - -void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, - mbedtls_md_type_t md_alg) { - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, - mbedtls_pk_context *key) { - ctx->key = key; -} - -int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, - const char *subject_name) { - return mbedtls_x509_string_to_names(&ctx->subject, subject_name); -} - -int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, - size_t val_len) { - return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, 0, val, - val_len); -} - -int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, - unsigned char key_usage) { - unsigned char buf[4] = {0}; - unsigned char *c; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - c = buf + 4; - - ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); - if (ret < 3 || ret > 4) - return (ret); - - ret = mbedtls_x509write_csr_set_extension( - ctx, MBEDTLS_OID_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), c, - (size_t)ret); - if (ret != 0) - return (ret); - - return (0); -} - -int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type) { - unsigned char buf[4] = {0}; - unsigned char *c; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - c = buf + 4; - - ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); - if (ret < 3 || ret > 4) - return (ret); - - ret = mbedtls_x509write_csr_set_extension( - ctx, MBEDTLS_OID_NS_CERT_TYPE, MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), - c, (size_t)ret); - if (ret != 0) - return (ret); - - return (0); -} - -static int -x509write_csr_der_internal(mbedtls_x509write_csr *ctx, unsigned char *buf, - size_t size, unsigned char *sig, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[64]; - size_t pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; - size_t hash_len; - psa_algorithm_t hash_alg = mbedtls_psa_translate_md(ctx->md_alg); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - /* Write the CSR backwards starting from the end of buf */ - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_x509_write_extensions(&c, buf, ctx->extensions)); - - if (len) { - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag( - &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET)); - - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_oid( - &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, - MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, mbedtls_asn1_write_tag( - &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD( - len, - mbedtls_asn1_write_tag( - &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); - - MBEDTLS_ASN1_CHK_ADD(pub_len, - mbedtls_pk_write_pubkey_der(ctx->key, buf, c - buf)); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, ctx->subject)); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - /* - * Sign the written CSR data into the sig buffer - * Note: hash errors can happen only after an internal error - */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (psa_hash_setup(&hash_operation, hash_alg) != PSA_SUCCESS) - return (MBEDTLS_ERR_X509_FATAL_ERROR); - - if (psa_hash_update(&hash_operation, c, len) != PSA_SUCCESS) - return (MBEDTLS_ERR_X509_FATAL_ERROR); - - if (psa_hash_finish(&hash_operation, hash, sizeof(hash), &hash_len) != - PSA_SUCCESS) { - return (MBEDTLS_ERR_X509_FATAL_ERROR); - } -#else /* MBEDTLS_USE_PSA_CRYPTO */ - ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); - if (ret != 0) - return (ret); -#endif - if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng)) != 0) { - return (ret); - } - - if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) - pk_alg = MBEDTLS_PK_RSA; - else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) - pk_alg = MBEDTLS_PK_ECDSA; - else - return (MBEDTLS_ERR_X509_INVALID_ALG); - - if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, &sig_oid, - &sig_oid_len)) != 0) { - return (ret); - } - - /* - * Move the written CSR data to the start of buf to create space for - * writing the signature into buf. - */ - memmove(buf, c, len); - - /* - * Write sig and its OID into buf backwards from the end of buf. - * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len - * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig( - &c2, buf + len, sig_oid, - sig_oid_len, sig, sig_len, pk_alg)); - - /* - * Compact the space between the CSR data and signature by moving the - * CSR data to the start of the signature. - */ - c2 -= len; - memmove(c2, buf, len); - - /* ASN encode the total size and tag the CSR data with it. */ - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c2, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - /* Zero the unused bytes at the start of buf */ - memset(buf, 0, c2 - buf); - - return ((int)len); -} - -int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, - size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - int ret; - unsigned char *sig; - -#if defined(TINYCRYPT_PRIMITIVES) - if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE + 1)) == NULL) -#else - if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) -#endif - { - return (MBEDTLS_ERR_X509_ALLOC_FAILED); - } - - ret = x509write_csr_der_internal(ctx, buf, size, sig, f_rng, p_rng); - - mbedtls_free(sig); - - return (ret); -} - -#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" -#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, - size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t olen = 0; - - if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, f_rng, p_rng)) < 0) { - return (ret); - } - - if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, - buf + size - ret, ret, buf, size, - &olen)) != 0) { - return (ret); - } - - return (0); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CSR_WRITE_C */ From 831c0c557044059b496d7cb61a0b34b32c2822df Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:30:23 +0530 Subject: [PATCH 04/11] WIP --- .../{tinycript_util.h => tinycrypt_util.h} | 2 + matter/mbedtls/tinycrypt/src/ecc.c | 52 ++++++++----------- matter/mbedtls/tinycrypt/src/ecc_dh.c | 10 ++-- matter/mbedtls/tinycrypt/src/ecc_dsa.c | 3 +- .../{tinycript_util.c => tinycrypt_util.c} | 2 +- 5 files changed, 33 insertions(+), 36 deletions(-) rename matter/mbedtls/tinycrypt/inc/tinycrypt/{tinycript_util.h => tinycrypt_util.h} (80%) rename matter/mbedtls/tinycrypt/src/{tinycript_util.c => tinycrypt_util.c} (99%) diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h similarity index 80% rename from matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h rename to matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h index a9eff6f9a5..f7515b6de3 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycript_util.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h @@ -8,6 +8,8 @@ void mbedtls_platform_random_buf(uint8_t *buf, size_t len); void *mbedtls_platform_memset(void *, int, size_t); void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); +void mbedtls_platform_random_delay(void); +uint32_t mbedtls_platform_random_in_range(uint32_t num); #endif // defined(SL_MBEDTLS_USE_TINYCRYPT) #endif // TINYCRYPT_PLATFORM_UTIL_H \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/ecc.c b/matter/mbedtls/tinycrypt/src/ecc.c index d2d46bb603..afcd406a0a 100644 --- a/matter/mbedtls/tinycrypt/src/ecc.c +++ b/matter/mbedtls/tinycrypt/src/ecc.c @@ -60,11 +60,11 @@ #include MBEDTLS_CONFIG_FILE #endif #if defined(SL_MBEDTLS_USE_TINYCRYPT) -#include -#include "mbedtls/platform_util.h" -#include "mbedtls/sha256.h" #include -#include "mbedtls/platform_util.h" +#include +#include +#include +#include #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM #ifndef asm #define asm __asm @@ -228,43 +228,37 @@ void uECC_vli_clear(uECC_word_t *vli) } #endif #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli){ +__asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) +{ #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif #if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - LDMIA r0 !, { r1, r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0 !, { r2, r3 } ORRS r1, r2 ORRS r1, - r3 LDMIA r0, { r0, r2, r3 } ORRS r1, r0 ORRS r1, r2 ORRS r1, r3 RSBS r1, r1, + LDMIA r0 !, { r1, r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0 !, { r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0, + { r0, r2, r3 } ORRS r1, r0 ORRS r1, r2 ORRS r1, r3 RSBS r1, r1, # 0 // C set if zero - MOVS r0, + MOVS r0, # 0 ADCS r0, - r0 BX lr + r0 BX lr #else - LDMIA r0 !, - { r1, r2, r3, ip } ORRS r1, - r2 ORRS r1, - r3 ORRS r1, - ip LDMIA r0, - { r0, r2, r3, ip } ORRS r1, - r0 ORRS r1, - r2 ORRS r1, - r3 ORRS r1, - ip + LDMIA r0 !, { r1, r2, r3, ip } ORRS r1, r2 ORRS r1, r3 ORRS r1, ip LDMIA r0, { r0, r2, r3, ip } ORRS r1, r0 ORRS r1, + r2 ORRS r1, r3 ORRS r1, + ip #ifdef __ARM_FEATURE_CLZ - CLZ r0, - r1 // 32 if zero - LSRS r0, - r0, + CLZ r0, + r1 // 32 if zero + LSRS r0, + r0, # 5 #else - RSBS r1, - r1, + RSBS r1, + r1, # 0 // C set if zero - MOVS r0, + MOVS r0, # 0 ADCS r0, - r0 + r0 #endif - BX lr + BX lr #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ @@ -547,7 +541,7 @@ static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *le # 0 // does not affect C flag ADCS r0, r0 // r0 := 0 + 0 + C = carry - POP + POP { r4 - r8, pc } diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index c765d052a3..79ba08f8b1 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -62,11 +62,11 @@ #include MBEDTLS_CONFIG_FILE #endif #if defined(SL_MBEDTLS_USE_TINYCRYPT) +#include +#include #include #include -#include -#include -#include "mbedtls/platform_util.h" +#include int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, unsigned int *d) { int ret = UECC_FAULT_DETECTED; @@ -139,12 +139,12 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, ui uECC_word_t _private[NUM_ECC_WORDS]; wordcount_t num_words = NUM_ECC_WORDS; wordcount_t num_bytes = NUM_ECC_BYTES; - int r = UECC_FAULT_DETECTED; + // int r = UECC_FAULT_DETECTED; /* Converting buffers to correct bit order: */ uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); uECC_vli_bytesToNative(_public, public_key, num_bytes); uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes); - r = EccPoint_mult_safer(_public, _public, _private); + int r = EccPoint_mult_safer(_public, _public, _private); uECC_vli_nativeToBytes(secret, num_bytes, _public); /* erasing temporary buffer used to store secret: */ mbedtls_platform_zeroize(_private, sizeof(_private)); diff --git a/matter/mbedtls/tinycrypt/src/ecc_dsa.c b/matter/mbedtls/tinycrypt/src/ecc_dsa.c index dbaa4e62e6..ee9527ed08 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dsa.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dsa.c @@ -60,9 +60,10 @@ #include MBEDTLS_CONFIG_FILE #endif #if defined(SL_MBEDTLS_USE_TINYCRYPT) +#include #include #include -#include "mbedtls/platform_util.h" +#include static void bits2int(uECC_word_t *native, const uint8_t *bits, unsigned bits_size) { unsigned num_n_bytes = BITS_TO_BYTES(NUM_ECC_BITS); diff --git a/matter/mbedtls/tinycrypt/src/tinycript_util.c b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c similarity index 99% rename from matter/mbedtls/tinycrypt/src/tinycript_util.c rename to matter/mbedtls/tinycrypt/src/tinycrypt_util.c index 950191fb05..2175f563ea 100644 --- a/matter/mbedtls/tinycrypt/src/tinycript_util.c +++ b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c @@ -21,7 +21,7 @@ // This files is not part of the tinycript librairy. It is used to define function tinycript requires that are not present in the Simplicity SDK mbedtls fork #include "mbedtls/platform_util.h" -#include +#include #if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) #include "platform_fault.h" From ebe86cf169091b938f5af5eca8cfd68bf3cc0519 Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:41:41 +0530 Subject: [PATCH 05/11] Initial commit --- matter/mbedtls/tinycrypt/inc/mbedtls/oid.h | 734 ++++ matter/mbedtls/tinycrypt/inc/mbedtls/pk.h | 1107 ++++++ matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h | 130 - .../tinycrypt/inc/tinycrypt/cbc_mode.h | 151 - .../tinycrypt/inc/tinycrypt/ccm_mode.h | 211 -- .../tinycrypt/inc/tinycrypt/cmac_mode.h | 194 - .../tinycrypt/inc/tinycrypt/ctr_mode.h | 108 - .../tinycrypt/inc/tinycrypt/ctr_prng.h | 166 - matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h | 139 - .../tinycrypt/inc/tinycrypt/hmac_prng.h | 164 - .../mbedtls/tinycrypt/inc/tinycrypt/sha256.h | 129 - matter/mbedtls/tinycrypt/src/aes_decrypt.c | 164 - matter/mbedtls/tinycrypt/src/aes_encrypt.c | 191 - matter/mbedtls/tinycrypt/src/cbc_mode.c | 114 - matter/mbedtls/tinycrypt/src/ccm_mode.c | 266 -- matter/mbedtls/tinycrypt/src/cmac_mode.c | 254 -- matter/mbedtls/tinycrypt/src/ctr_mode.c | 85 - matter/mbedtls/tinycrypt/src/ctr_prng.c | 283 -- matter/mbedtls/tinycrypt/src/error.c | 1064 ------ matter/mbedtls/tinycrypt/src/hmac.c | 148 - matter/mbedtls/tinycrypt/src/hmac_prng.c | 212 -- matter/mbedtls/tinycrypt/src/oid.c | 1166 ++++++ matter/mbedtls/tinycrypt/src/pk.c | 982 +++++ matter/mbedtls/tinycrypt/src/pk_wrap.c | 1850 +++++++++ matter/mbedtls/tinycrypt/src/pk_wrap.h | 168 + matter/mbedtls/tinycrypt/src/pkparse.c | 1857 +++++++++ matter/mbedtls/tinycrypt/src/pkwrite.c | 848 +++++ matter/mbedtls/tinycrypt/src/tinycrypt_util.c | 5 +- matter/mbedtls/tinycrypt/src/x509_crt.c | 3308 +++++++++++++++++ matter/mbedtls/tinycrypt/src/x509write_csr.c | 343 ++ 30 files changed, 12366 insertions(+), 4175 deletions(-) create mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/oid.h create mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/pk.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h delete mode 100644 matter/mbedtls/tinycrypt/src/aes_decrypt.c delete mode 100644 matter/mbedtls/tinycrypt/src/aes_encrypt.c delete mode 100644 matter/mbedtls/tinycrypt/src/cbc_mode.c delete mode 100644 matter/mbedtls/tinycrypt/src/ccm_mode.c delete mode 100644 matter/mbedtls/tinycrypt/src/cmac_mode.c delete mode 100644 matter/mbedtls/tinycrypt/src/ctr_mode.c delete mode 100644 matter/mbedtls/tinycrypt/src/ctr_prng.c delete mode 100644 matter/mbedtls/tinycrypt/src/error.c delete mode 100644 matter/mbedtls/tinycrypt/src/hmac.c delete mode 100644 matter/mbedtls/tinycrypt/src/hmac_prng.c create mode 100644 matter/mbedtls/tinycrypt/src/oid.c create mode 100644 matter/mbedtls/tinycrypt/src/pk.c create mode 100644 matter/mbedtls/tinycrypt/src/pk_wrap.c create mode 100644 matter/mbedtls/tinycrypt/src/pk_wrap.h create mode 100644 matter/mbedtls/tinycrypt/src/pkparse.c create mode 100644 matter/mbedtls/tinycrypt/src/pkwrite.c create mode 100644 matter/mbedtls/tinycrypt/src/x509_crt.c create mode 100644 matter/mbedtls/tinycrypt/src/x509write_csr.c diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h b/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h new file mode 100644 index 0000000000..9545072296 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h @@ -0,0 +1,734 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * 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. + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#include "mbedtls/md.h" + +/** OID is not found. */ +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E +/** output buffer is too small */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B + +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Maximum number of OID components allowed + */ +#define MBEDTLS_OID_MAX_COMPONENTS 128 + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */ +#define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_THAWTE +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD \ + "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" + +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */ + + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +#define MBEDTLS_OID_HMAC_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */ + +#define MBEDTLS_OID_HMAC_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */ + +#define MBEDTLS_OID_HMAC_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */ + +#define MBEDTLS_OID_HMAC_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */ + +#define MBEDTLS_OID_HMAC_RIPEMD160 MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG \ + MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#7 OIDs + */ +#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ +#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ +#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ +#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ +#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ +#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +/* + * EC key algorithms from RFC 8410 + */ + +#define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */ +#define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */ +#define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */ +#define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t { + const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ + size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) + const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ + const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ +#endif +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); + +/** + * \brief Translate a string containing a dotted-decimal + * representation of an ASN.1 OID into its encoded form + * (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D"). + * On success, this function allocates oid->buf from the + * heap. It must be freed by the caller using mbedtls_free(). + * + * \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID + * \param oid_str string representation of the OID to parse + * \param size length of the OID string, not including any null terminator + * + * \return 0 if successful + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not + * represent a valid OID + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to + * allocate oid->buf + */ +int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size); + +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen); + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen); + +/** + * \brief Translate AlgorithmIdentifier OID into an EC group identifier, + * for curves that are directly encoded at this level + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); + +/** + * \brief Translate EC group identifier into AlgorithmIdentifier OID, + * for curves that are directly encoded at this level + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); +#endif + +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, const char **desc); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h b/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h new file mode 100644 index 0000000000..68ebd73885 --- /dev/null +++ b/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h @@ -0,0 +1,1107 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * 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. + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa/crypto.h" +#endif + +/** Memory allocation failed. */ +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 +/** Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 +/** Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 +/** Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 +/** Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 +/** The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 +/** Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 +/** Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 +/** The output buffer is too small. */ +#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options { + /** The digest to use for MGF1 in PSS. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is + * disabled, this must be equal to the \c md_alg argument passed + * to mbedtls_pk_verify_ext(). In a future version of the library, + * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is + * enabled regardless of the status of #MBEDTLS_RSA_C. + */ + mbedtls_md_type_t mgf1_hash_id; + + /** The expected length of the salt, in bytes. This may be + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * + * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only + * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be + * ignored (allowing any salt length). + */ + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + +/* Internal helper to define which fields in the pk_context structure below + * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly) + * format. It should be noted that this only affects how data is stored, not + * which functions are used for various operations. The overall picture looks + * like this: + * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data + * structure and legacy functions + * - if USE_PSA is defined and + * - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly + * format and use PSA functions + * - if !ECP_C then use new raw data and PSA functions directly. + * + * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long + * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the + * ecp_keypair structure inside the pk_context so they can modify it using + * ECP functions which are not under PK module's control. + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ + !defined(MBEDTLS_ECP_C) +#define MBEDTLS_PK_USE_PSA_EC_DATA +#endif + +/* Helper symbol to state that the PK module has support for EC keys. This + * can either be provided through the legacy ECP solution or through the + * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA. */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_ECP_C) +#define MBEDTLS_PK_HAVE_ECC_KEYS +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */ + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum { + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, + MBEDTLS_PK_DEBUG_PSA_EC, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item { + mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); + const char *MBEDTLS_PRIVATE(name); + void *MBEDTLS_PRIVATE(value); +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + * + * \note The library does not support custom pk info structures, + * only built-in structures returned by + * mbedtls_cipher_info_from_type(). + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +#define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context { + const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ + /* The following field is used to store the ID of a private key in the + * following cases: + * - opaque key when MBEDTLS_PSA_CRYPTO_C is defined + * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case: + * - the pk_ctx above is not not used to store the private key anymore. + * Actually that field not populated at all in this case because also + * the public key will be stored in raw format as explained below + * - this ID is used for all private key operations (ex: sign, check + * key pair, key write, etc) using PSA functions + * + * Note: this private key storing solution only affects EC keys, not the + * other ones. The latters still use the pk_ctx to store their own + * context. + * + * Note: this priv_id is guarded by MBEDTLS_PSA_CRYPTO_C and not by + * MBEDTLS_PK_USE_PSA_EC_DATA (as the public counterpart below) because, + * when working with opaque keys, it can be used also in + * mbedtls_pk_sign_ext for RSA keys. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ +#else + uint32_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ +#endif /* MBEDTLS_PSA_CRYPTO_C */ + /* The following fields are meant for storing the public key in raw format + * which is handy for: + * - easily importing it into the PSA context + * - reducing the ECP module dependencies in the PK one. + * + * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled: + * - the pk_ctx above is not used anymore for storing the public key + * inside the ecp_keypair structure + * - the following fields are used for all public key operations: signature + * verify, key pair check and key write. + * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy + * ecp_keypair structure is used for storing the public key and performing + * all the operations. + * + * Note: This new public key storing solution only works for EC keys, not + * other ones. The latters still use pk_ctx to store their own + * context. + */ + uint8_t MBEDTLS_PRIVATE(pub_raw)[66 * 2 + 1]; /**< Raw public key */ + size_t MBEDTLS_PRIVATE(pub_raw_len); /**< Valid bytes in "pub_raw" */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_ecc_family_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ +#else + uint8_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + size_t MBEDTLS_PRIVATE(ec_bits); /**< Curve's bits of pk */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct { + const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void *MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len); +typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init(mbedtls_pk_context *ctx); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free(mbedtls_pk_context *ctx); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC or RSA key + * pair (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC or RSA + * key pairs (that is, keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key identifier). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, + const mbedtls_svc_key_id_t key); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) +{ + return (mbedtls_pk_get_bitlen(ctx) + 7) / 8; +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Tell if context can do the operation given by PSA algorithm + * + * \param ctx The context to query. It must have been initialized. + * \param alg PSA algorithm to check against, the following are allowed: + * PSA_ALG_RSA_PKCS1V15_SIGN(hash), + * PSA_ALG_RSA_PSS(hash), + * PSA_ALG_RSA_PKCS1V15_CRYPT, + * PSA_ALG_ECDSA(hash), + * PSA_ALG_ECDH, where hash is a specific hash. + * \param usage PSA usage flag to check against, must be composed of: + * PSA_KEY_USAGE_SIGN_HASH + * PSA_KEY_USAGE_DECRYPT + * PSA_KEY_USAGE_DERIVE. + * Context key must match all passed usage flags. + * + * \warning Since the set of allowed algorithms and usage flags may be + * expanded in the future, the return value \c 0 should not + * be taken in account for non-allowed algorithms and usage + * flags. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type, for non-allowed algorithms and usage flags, or + * for a context that has been initialized but not set up + * or that has been cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used. + * This can be #MBEDTLS_MD_NONE if the signature algorithm + * does not rely on a hash algorithm (non-deterministic + * ECDSA, RSA PKCS#1 v1.5). + * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then + * \p hash is the DigestInfo structure used by RFC 8017 + * §9.2 steps 3–6. If \p md_alg is a valid hash + * algorithm then \p hash is the digest itself, and this + * function calculates the DigestInfo encoding internally. + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig but its length is less than \p sig_len, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + */ +int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig but its length is less than \p sig_len, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. Note that if + * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not + * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. + */ +int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +#if defined(MBEDTLS_PSA_CRYPTO_C) +/** + * \brief Make signature given a signature type. + * + * \param pk_type Signature type. + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, + * see #PSA_ALG_RSA_PSS for a description of PSS options used. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + * + */ +int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note \p f_rng is used for padding generation. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal RSA context held by the PK context, or NULL. + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) +{ + switch (mbedtls_pk_get_type(&pk)) { + case MBEDTLS_PK_RSA: + return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx); + default: + return NULL; + } +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning This function can only be used when the type of the context, as + * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, + * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. + * Ensuring that is the caller's responsibility. + * Alternatively, you can check whether this function returns NULL. + * + * \return The internal EC context held by the PK context, or NULL. + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) +{ + switch (mbedtls_pk_get_type(&pk)) { + case MBEDTLS_PK_ECKEY: + case MBEDTLS_PK_ECKEY_DH: + case MBEDTLS_PK_ECDSA: + return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); + default: + return NULL; + } +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for + * limitations. + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto + * subsystem must have been initialized by calling + * psa_crypto_init() before calling this function. + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, + const char *path, const char *password, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC or RSA key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \param pk Input: the EC or RSA key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param key Output: a PSA key identifier. + * It's the caller's responsibility to call + * psa_destroy_key() on that key identifier after calling + * mbedtls_pk_free() on the PK context. + * \param alg The algorithm to allow for use with that key. + * \param usage The usage to allow for use with that key. + * \param alg2 The secondary algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h deleted file mode 100644 index b612213a0e..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/aes.h +++ /dev/null @@ -1,130 +0,0 @@ -/* aes.h - TinyCrypt interface to an AES-128 implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to an AES-128 implementation. - * - * Overview: AES-128 is a NIST approved block cipher specified in - * FIPS 197. Block ciphers are deterministic algorithms that - * perform a transformation specified by a symmetric key in fixed- - * length data sets, also called blocks. - * - * Security: AES-128 provides approximately 128 bits of security. - * - * Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key. - * - * 2) call tc_aes_encrypt/decrypt to process the data. - */ - -#ifndef __TC_AES_H__ -#define __TC_AES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define Nb (4) /* number of columns (32-bit words) comprising the state */ -#define Nk (4) /* number of 32-bit words comprising the key */ -#define Nr (10) /* number of rounds */ -#define TC_AES_BLOCK_SIZE (Nb*Nk) -#define TC_AES_KEY_SIZE (Nb*Nk) - -typedef struct tc_aes_key_sched_struct { - unsigned int words[Nb*(Nr+1)]; -} *TCAesKeySched_t; - -/** - * @brief Set AES-128 encryption key - * Uses key k to initialize s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL - * @note This implementation skips the additional steps required for keys - * larger than 128 bits, and must not be used for AES-192 or - * AES-256 key schedule -- see FIPS 197 for details - * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct - * @param k IN -- points to the AES key - */ -int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k); - -/** - * @brief AES-128 Encryption procedure - * Encrypts contents of in buffer into out buffer under key; - * schedule s - * @note Assumes s was initialized by aes_set_encrypt_key; - * out and in point to 16 byte buffers - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL - * @param out IN/OUT -- buffer to receive ciphertext block - * @param in IN -- a plaintext block to encrypt - * @param s IN -- initialized AES key schedule - */ -int tc_aes_encrypt(uint8_t *out, const uint8_t *in, - const TCAesKeySched_t s); - -/** - * @brief Set the AES-128 decryption key - * Uses key k to initialize s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL - * @note This is the implementation of the straightforward inverse cipher - * using the cipher documented in FIPS-197 figure 12, not the - * equivalent inverse cipher presented in Figure 15 - * @warning This routine skips the additional steps required for keys larger - * than 128, and must not be used for AES-192 or AES-256 key - * schedule -- see FIPS 197 for details - * @param s IN/OUT -- initialized struct tc_aes_key_sched_struct - * @param k IN -- points to the AES key - */ -int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k); - -/** - * @brief AES-128 Encryption procedure - * Decrypts in buffer into out buffer under key schedule s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL - * @note Assumes s was initialized by aes_set_encrypt_key - * out and in point to 16 byte buffers - * @param out IN/OUT -- buffer to receive ciphertext block - * @param in IN -- a plaintext block to encrypt - * @param s IN -- initialized AES key schedule - */ -int tc_aes_decrypt(uint8_t *out, const uint8_t *in, - const TCAesKeySched_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_AES_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h deleted file mode 100644 index 4a837fd01a..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/cbc_mode.h +++ /dev/null @@ -1,151 +0,0 @@ -/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CBC mode implementation. - * - * Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of - * operation defined in SP 800-38a. It can be used with any block - * cipher to provide confidentiality of strings whose lengths are - * multiples of the block_size of the underlying block cipher. - * TinyCrypt hard codes AES as the block cipher. - * - * Security: CBC mode provides data confidentiality given that the maximum - * number q of blocks encrypted under a single key satisfies - * q < 2^63, which is not a practical constraint (it is considered a - * good practice to replace the encryption when q == 2^56). CBC mode - * provides NO data integrity. - * - * CBC mode assumes that the IV value input into the - * tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library - * provides HMAC-PRNG module, which generates suitable IVs. Other - * methods for generating IVs are acceptable, provided that the - * values of the IVs generated appear random to any adversary, - * including someone with complete knowledge of the system design. - * - * The randomness property on which CBC mode's security depends is - * the unpredictability of the IV. Since it is unpredictable, this - * means in practice that CBC mode requires that the IV is stored - * somehow with the ciphertext in order to recover the plaintext. - * - * TinyCrypt CBC encryption prepends the IV to the ciphertext, - * because this affords a more efficient (few buffers) decryption. - * Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always - * 16 bytes larger than the plaintext buffer. - * - * Requires: AES-128 - * - * Usage: 1) call tc_cbc_mode_encrypt to encrypt data. - * - * 2) call tc_cbc_mode_decrypt to decrypt data. - * - */ - -#ifndef __TC_CBC_MODE_H__ -#define __TC_CBC_MODE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief CBC encryption procedure - * CBC encrypts inlen bytes of the in buffer into the out buffer - * using the encryption key schedule provided, prepends iv to out - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * ctr == NULL or - * sched == NULL or - * inlen == 0 or - * (inlen % TC_AES_BLOCK_SIZE) != 0 or - * (outlen % TC_AES_BLOCK_SIZE) != 0 or - * outlen != inlen + TC_AES_BLOCK_SIZE - * @note Assumes: - sched has been configured by aes_set_encrypt_key - * - iv contains a 16 byte random string - * - out buffer is large enough to hold the ciphertext + iv - * - out buffer is a contiguous buffer - * - in holds the plaintext and is a contiguous buffer - * - inlen gives the number of bytes in the in buffer - * @param out IN/OUT -- buffer to receive the ciphertext - * @param outlen IN -- length of ciphertext buffer in bytes - * @param in IN -- plaintext to encrypt - * @param inlen IN -- length of plaintext buffer in bytes - * @param iv IN -- the IV for the this encrypt/decrypt - * @param sched IN -- AES key schedule for this encrypt - */ -int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched); - -/** - * @brief CBC decryption procedure - * CBC decrypts inlen bytes of the in buffer into the out buffer - * using the provided encryption key schedule - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * sched == NULL or - * inlen == 0 or - * outlen == 0 or - * (inlen % TC_AES_BLOCK_SIZE) != 0 or - * (outlen % TC_AES_BLOCK_SIZE) != 0 or - * outlen != inlen + TC_AES_BLOCK_SIZE - * @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are - * contiguous. This allows for a very efficient decryption - * algorithm that would not otherwise be possible - * - sched was configured by aes_set_decrypt_key - * - out buffer is large enough to hold the decrypted plaintext - * and is a contiguous buffer - * - inlen gives the number of bytes in the in buffer - * @param out IN/OUT -- buffer to receive decrypted data - * @param outlen IN -- length of plaintext buffer in bytes - * @param in IN -- ciphertext to decrypt, including IV - * @param inlen IN -- length of ciphertext buffer in bytes - * @param iv IN -- the IV for the this encrypt/decrypt - * @param sched IN -- AES key schedule for this decrypt - * - */ -int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CBC_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h deleted file mode 100644 index 69c798e2f5..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ccm_mode.h +++ /dev/null @@ -1,211 +0,0 @@ -/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CCM mode implementation. - * - * Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of - * operation defined in SP 800-38C. - * - * TinyCrypt CCM implementation accepts: - * - * 1) Both non-empty payload and associated data (it encrypts and - * authenticates the payload and also authenticates the associated - * data); - * 2) Non-empty payload and empty associated data (it encrypts and - * authenticates the payload); - * 3) Non-empty associated data and empty payload (it degenerates to - * an authentication mode on the associated data). - * - * TinyCrypt CCM implementation accepts associated data of any length - * between 0 and (2^16 - 2^8) bytes. - * - * Security: The mac length parameter is an important parameter to estimate the - * security against collision attacks (that aim at finding different - * messages that produce the same authentication tag). TinyCrypt CCM - * implementation accepts any even integer between 4 and 16, as - * suggested in SP 800-38C. - * - * RFC-3610, which also specifies CCM, presents a few relevant - * security suggestions, such as: it is recommended for most - * applications to use a mac length greater than 8. Besides, the - * usage of the same nonce for two different messages which are - * encrypted with the same key destroys the security of CCM mode. - * - * Requires: AES-128 - * - * Usage: 1) call tc_ccm_config to configure. - * - * 2) call tc_ccm_mode_encrypt to encrypt data and generate tag. - * - * 3) call tc_ccm_mode_decrypt to decrypt data and verify tag. - */ - -#ifndef __TC_CCM_MODE_H__ -#define __TC_CCM_MODE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */ -#define TC_CCM_AAD_MAX_BYTES 0xff00 - -/* max message size in bytes: 2^(8L) = 2^16 = 65536 */ -#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000 - -/* struct tc_ccm_mode_struct represents the state of a CCM computation */ -typedef struct tc_ccm_mode_struct { - TCAesKeySched_t sched; /* AES key schedule */ - uint8_t *nonce; /* nonce required by CCM */ - unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */ -} *TCCcmMode_t; - -/** - * @brief CCM configuration procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * c == NULL or - * sched == NULL or - * nonce == NULL or - * mlen != {4, 6, 8, 10, 12, 16} - * @param c -- CCM state - * @param sched IN -- AES key schedule - * @param nonce IN - nonce - * @param nlen -- nonce length in bytes - * @param mlen -- mac length in bytes (parameter t in SP-800 38C) - */ -int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, - unsigned int nlen, unsigned int mlen); - -/** - * @brief CCM tag generation and encryption procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * c == NULL or - * ((plen > 0) and (payload == NULL)) or - * ((alen > 0) and (associated_data == NULL)) or - * (alen >= TC_CCM_AAD_MAX_BYTES) or - * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or - * (olen < plen + maclength) - * - * @param out OUT -- encrypted data - * @param olen IN -- output length in bytes - * @param associated_data IN -- associated data - * @param alen IN -- associated data length in bytes - * @param payload IN -- payload - * @param plen IN -- payload length in bytes - * @param c IN -- CCM state - * - * @note: out buffer should be at least (plen + c->mlen) bytes long. - * - * @note: The sequence b for encryption is formatted as follows: - * b = [FLAGS | nonce | counter ], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * counter is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-7 btis: always 0's - * - * @note: The sequence b for authentication is formatted as follows: - * b = [FLAGS | nonce | length(mac length)], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * length(mac length) is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-5 bits: mac length (encoded as: (mlen-2)/2) - * 6: Adata (0 if alen == 0, and 1 otherwise) - * 7: always 0 - */ -int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c); - -/** - * @brief CCM decryption and tag verification procedure - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * c == NULL or - * ((plen > 0) and (payload == NULL)) or - * ((alen > 0) and (associated_data == NULL)) or - * (alen >= TC_CCM_AAD_MAX_BYTES) or - * (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or - * (olen < plen - c->mlen) - * - * @param out OUT -- decrypted data - * @param associated_data IN -- associated data - * @param alen IN -- associated data length in bytes - * @param payload IN -- payload - * @param plen IN -- payload length in bytes - * @param c IN -- CCM state - * - * @note: out buffer should be at least (plen - c->mlen) bytes long. - * - * @note: The sequence b for encryption is formatted as follows: - * b = [FLAGS | nonce | counter ], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * counter is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-7 btis: always 0's - * - * @note: The sequence b for authentication is formatted as follows: - * b = [FLAGS | nonce | length(mac length)], where: - * FLAGS is 1 byte long - * nonce is 13 bytes long - * length(mac length) is 2 bytes long - * The byte FLAGS is composed by the following 8 bits: - * 0-2 bits: used to represent the value of q-1 - * 3-5 bits: mac length (encoded as: (mlen-2)/2) - * 6: Adata (0 if alen == 0, and 1 otherwise) - * 7: always 0 - */ -int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, unsigned int plen, - TCCcmMode_t c); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CCM_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h deleted file mode 100644 index f44b0a53c1..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/cmac_mode.h +++ /dev/null @@ -1,194 +0,0 @@ -/* cmac_mode.h -- interface to a CMAC implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CMAC implementation. - * - * Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm - * for computing a MAC using a block cipher. It can compute the MAC - * for a byte string of any length. It is distinguished from CBC-MAC - * in the processing of the final message block; CMAC uses a - * different technique to compute the final message block is full - * size or only partial, while CBC-MAC uses the same technique for - * both. This difference permits CMAC to be applied to variable - * length messages, while all messages authenticated by CBC-MAC must - * be the same length. - * - * Security: AES128-CMAC mode of operation offers 64 bits of security against - * collision attacks. Note however that an external attacker cannot - * generate the tags him/herself without knowing the MAC key. In this - * sense, to attack the collision property of AES128-CMAC, an - * external attacker would need the cooperation of the legal user to - * produce an exponentially high number of tags (e.g. 2^64) to - * finally be able to look for collisions and benefit from them. As - * an extra precaution, the current implementation allows to at most - * 2^48 calls to the tc_cmac_update function before re-calling - * tc_cmac_setup (allowing a new key to be set), as suggested in - * Appendix B of SP 800-38B. - * - * Requires: AES-128 - * - * Usage: This implementation provides a "scatter-gather" interface, so that - * the CMAC value can be computed incrementally over a message - * scattered in different segments throughout memory. Experience shows - * this style of interface tends to minimize the burden of programming - * correctly. Like all symmetric key operations, it is session - * oriented. - * - * To begin a CMAC session, use tc_cmac_setup to initialize a struct - * tc_cmac_struct with encryption key and buffer. Our implementation - * always assume that the AES key to be the same size as the block - * cipher block size. Once setup, this data structure can be used for - * many CMAC computations. - * - * Once the state has been setup with a key, computing the CMAC of - * some data requires three steps: - * - * (1) first use tc_cmac_init to initialize a new CMAC computation. - * (2) next mix all of the data into the CMAC computation state using - * tc_cmac_update. If all of the data resides in a single data - * segment then only one tc_cmac_update call is needed; if data - * is scattered throughout memory in n data segments, then n calls - * will be needed. CMAC IS ORDER SENSITIVE, to be able to detect - * attacks that swap bytes, so the order in which data is mixed - * into the state is critical! - * (3) Once all of the data for a message has been mixed, use - * tc_cmac_final to compute the CMAC tag value. - * - * Steps (1)-(3) can be repeated as many times as you want to CMAC - * multiple messages. A practical limit is 2^48 1K messages before you - * have to change the key. - * - * Once you are done computing CMAC with a key, it is a good idea to - * destroy the state so an attacker cannot recover the key; use - * tc_cmac_erase to accomplish this. - */ - -#ifndef __TC_CMAC_MODE_H__ -#define __TC_CMAC_MODE_H__ - -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* padding for last message block */ -#define TC_CMAC_PADDING 0x80 - -/* struct tc_cmac_struct represents the state of a CMAC computation */ -typedef struct tc_cmac_struct { -/* initialization vector */ - uint8_t iv[TC_AES_BLOCK_SIZE]; -/* used if message length is a multiple of block_size bytes */ - uint8_t K1[TC_AES_BLOCK_SIZE]; -/* used if message length isn't a multiple block_size bytes */ - uint8_t K2[TC_AES_BLOCK_SIZE]; -/* where to put bytes that didn't fill a block */ - uint8_t leftover[TC_AES_BLOCK_SIZE]; -/* identifies the encryption key */ - unsigned int keyid; -/* next available leftover location */ - unsigned int leftover_offset; -/* AES key schedule */ - TCAesKeySched_t sched; -/* calls to tc_cmac_update left before re-key */ - uint64_t countdown; -} *TCCmacState_t; - -/** - * @brief Configures the CMAC state to use the given AES key - * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL or - * key == NULL - * - * @param s IN/OUT -- the state to set up - * @param key IN -- the key to use - * @param sched IN -- AES key schedule - */ -int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, - TCAesKeySched_t sched); - -/** - * @brief Erases the CMAC state - * @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL - * - * @param s IN/OUT -- the state to erase - */ -int tc_cmac_erase(TCCmacState_t s); - -/** - * @brief Initializes a new CMAC computation - * @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL - * - * @param s IN/OUT -- the state to initialize - */ -int tc_cmac_init(TCCmacState_t s); - -/** - * @brief Incrementally computes CMAC over the next data segment - * @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL or - * if data == NULL when dlen > 0 - * - * @param s IN/OUT -- the CMAC state - * @param data IN -- the next data segment to MAC - * @param dlen IN -- the length of data in bytes - */ -int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen); - -/** - * @brief Generates the tag from the CMAC state - * @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag - * returns TC_CRYPTO_FAIL (0) if: - * tag == NULL or - * s == NULL - * - * @param tag OUT -- the CMAC tag - * @param s IN -- CMAC state - */ -int tc_cmac_final(uint8_t *tag, TCCmacState_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CMAC_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h deleted file mode 100644 index dc221f9ee7..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_mode.h +++ /dev/null @@ -1,108 +0,0 @@ -/* ctr_mode.h - TinyCrypt interface to CTR mode */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to CTR mode. - * - * Overview: CTR (pronounced "counter") mode is a NIST approved mode of - * operation defined in SP 800-38a. It can be used with any - * block cipher to provide confidentiality of strings of any - * length. TinyCrypt hard codes AES128 as the block cipher. - * - * Security: CTR mode achieves confidentiality only if the counter value is - * never reused with a same encryption key. If the counter is - * repeated, than an adversary might be able to defeat the scheme. - * - * A usual method to ensure different counter values refers to - * initialize the counter in a given value (0, for example) and - * increases it every time a new block is enciphered. This naturally - * leaves to a limitation on the number q of blocks that can be - * enciphered using a same key: q < 2^(counter size). - * - * TinyCrypt uses a counter of 32 bits. This means that after 2^32 - * block encryptions, the counter will be reused (thus losing CBC - * security). 2^32 block encryptions should be enough for most of - * applications targeting constrained devices. Applications intended - * to encrypt a larger number of blocks must replace the key after - * 2^32 block encryptions. - * - * CTR mode provides NO data integrity. - * - * Requires: AES-128 - * - * Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt. - * - */ - -#ifndef __TC_CTR_MODE_H__ -#define __TC_CTR_MODE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief CTR mode encryption/decryption procedure. - * CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL or - * in == NULL or - * ctr == NULL or - * sched == NULL or - * inlen == 0 or - * outlen == 0 or - * inlen != outlen - * @note Assumes:- The current value in ctr has NOT been used with sched - * - out points to inlen bytes - * - in points to inlen bytes - * - ctr is an integer counter in littleEndian format - * - sched was initialized by aes_set_encrypt_key - * @param out OUT -- produced ciphertext (plaintext) - * @param outlen IN -- length of ciphertext buffer in bytes - * @param in IN -- data to encrypt (or decrypt) - * @param inlen IN -- length of input data in bytes - * @param ctr IN/OUT -- the current counter value - * @param sched IN -- an initialized AES key schedule - */ -int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CTR_MODE_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h deleted file mode 100644 index 9be06dbb16..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ctr_prng.h +++ /dev/null @@ -1,166 +0,0 @@ -/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */ - -/* - * Copyright (c) 2016, Chris Morrison - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a CTR-PRNG implementation. - * - * Overview: A pseudo-random number generator (PRNG) generates a sequence - * of numbers that have a distribution close to the one expected - * for a sequence of truly random numbers. The NIST Special - * Publication 800-90A specifies several mechanisms to generate - * sequences of pseudo random numbers, including the CTR-PRNG one - * which is based on AES. TinyCrypt implements CTR-PRNG with - * AES-128. - * - * Security: A cryptographically secure PRNG depends on the existence of an - * entropy source to provide a truly random seed as well as the - * security of the primitives used as the building blocks (AES-128 - * in this instance). - * - * Requires: - AES-128 - * - * Usage: 1) call tc_ctr_prng_init to seed the prng context - * - * 2) call tc_ctr_prng_reseed to mix in additional entropy into - * the prng context - * - * 3) call tc_ctr_prng_generate to output the pseudo-random data - * - * 4) call tc_ctr_prng_uninstantiate to zero out the prng context - */ - -#ifndef __TC_CTR_PRNG_H__ -#define __TC_CTR_PRNG_H__ - -#include - -#define TC_CTR_PRNG_RESEED_REQ -1 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - /* updated each time another BLOCKLEN_BYTES bytes are produced */ - uint8_t V[TC_AES_BLOCK_SIZE]; - - /* updated whenever the PRNG is reseeded */ - struct tc_aes_key_sched_struct key; - - /* number of requests since initialization/reseeding */ - uint64_t reseedCount; -} TCCtrPrng_t; - - -/** - * @brief CTR-PRNG initialization procedure - * Initializes prng context with entropy and personalization string (if any) - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * entropy == NULL, - * entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) - * @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of - * both the entropy and personalization inputs are used - - * supplying additional bytes has no effect. - * @param ctx IN/OUT -- the PRNG context to initialize - * @param entropy IN -- entropy used to seed the PRNG - * @param entropyLen IN -- entropy length in bytes - * @param personalization IN -- personalization string used to seed the PRNG - * (may be null) - * @param plen IN -- personalization length in bytes - * - */ -int tc_ctr_prng_init(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const personalization, - unsigned int pLen); - -/** - * @brief CTR-PRNG reseed procedure - * Mixes entropy and additional_input into the prng context - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * entropy == NULL, - * entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) - * @note It is better to reseed an existing prng context rather than - * re-initialise, so that any existing entropy in the context is - * presereved. This offers some protection against undetected failures - * of the entropy source. - * @note Assumes tc_ctr_prng_init has been called for ctx - * @param ctx IN/OUT -- the PRNG state - * @param entropy IN -- entropy to mix into the prng - * @param entropylen IN -- length of entropy in bytes - * @param additional_input IN -- additional input to the prng (may be null) - * @param additionallen IN -- additional input length in bytes - */ -int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const additional_input, - unsigned int additionallen); - -/** - * @brief CTR-PRNG generate procedure - * Generates outlen pseudo-random bytes into out buffer, updates prng - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed - * returns TC_CRYPTO_FAIL (0) if: - * ctx == NULL, - * out == NULL, - * outlen >= 2^16 - * @note Assumes tc_ctr_prng_init has been called for ctx - * @param ctx IN/OUT -- the PRNG context - * @param additional_input IN -- additional input to the prng (may be null) - * @param additionallen IN -- additional input length in bytes - * @param out IN/OUT -- buffer to receive output - * @param outlen IN -- size of out buffer in bytes - */ -int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, - uint8_t const * const additional_input, - unsigned int additionallen, - uint8_t * const out, - unsigned int outlen); - -/** - * @brief CTR-PRNG uninstantiate procedure - * Zeroes the internal state of the supplied prng context - * @return none - * @param ctx IN/OUT -- the PRNG context - */ -void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CTR_PRNG_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h deleted file mode 100644 index 3a081494a8..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac.h +++ /dev/null @@ -1,139 +0,0 @@ -/* hmac.h - TinyCrypt interface to an HMAC implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to an HMAC implementation. - * - * Overview: HMAC is a message authentication code based on hash functions. - * TinyCrypt hard codes SHA-256 as the hash function. A message - * authentication code based on hash functions is also called a - * keyed cryptographic hash function since it performs a - * transformation specified by a key in an arbitrary length data - * set into a fixed length data set (also called tag). - * - * Security: The security of the HMAC depends on the length of the key and - * on the security of the hash function. Note that HMAC primitives - * are much less affected by collision attacks than their - * corresponding hash functions. - * - * Requires: SHA-256 - * - * Usage: 1) call tc_hmac_set_key to set the HMAC key. - * - * 2) call tc_hmac_init to initialize a struct hash_state before - * processing the data. - * - * 3) call tc_hmac_update to process the next input segment; - * tc_hmac_update can be called as many times as needed to process - * all of the segments of the input; the order is important. - * - * 4) call tc_hmac_final to out put the tag. - */ - -#ifndef __TC_HMAC_H__ -#define __TC_HMAC_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct tc_hmac_state_struct { - /* the internal state required by h */ - struct tc_sha256_state_struct hash_state; - /* HMAC key schedule */ - uint8_t key[2*TC_SHA256_BLOCK_SIZE]; -}; -typedef struct tc_hmac_state_struct *TCHmacState_t; - -/** - * @brief HMAC set key procedure - * Configures ctx to use key - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if - * ctx == NULL or - * key == NULL or - * key_size == 0 - * @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial - * @param key IN -- the HMAC key to configure - * @param key_size IN -- the HMAC key size - */ -int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, - unsigned int key_size); - -/** - * @brief HMAC init procedure - * Initializes ctx to begin the next HMAC operation - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL - * @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to init - */ -int tc_hmac_init(TCHmacState_t ctx); - -/** - * @brief HMAC update procedure - * Mixes data_length bytes addressed by data into state - * @return returns TC_CRYPTO_SUCCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL - * @note Assumes state has been initialized by tc_hmac_init - * @param ctx IN/OUT -- state of HMAC computation so far - * @param data IN -- data to incorporate into state - * @param data_length IN -- size of data in bytes - */ -int tc_hmac_update(TCHmacState_t ctx, const void *data, - unsigned int data_length); - -/** - * @brief HMAC final procedure - * Writes the HMAC tag into the tag buffer - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * tag == NULL or - * ctx == NULL or - * key == NULL or - * taglen != TC_SHA256_DIGEST_SIZE - * @note ctx is erased before exiting. This should never be changed/removed. - * @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes - * state has been initialized by tc_hmac_init - * @param tag IN/OUT -- buffer to receive computed HMAC tag - * @param taglen IN -- size of tag in bytes - * @param ctx IN/OUT -- the HMAC state for computing tag - */ -int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx); - -#ifdef __cplusplus -} -#endif - -#endif /*__TC_HMAC_H__*/ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h deleted file mode 100644 index ad12cbbf0f..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/hmac_prng.h +++ /dev/null @@ -1,164 +0,0 @@ -/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to an HMAC-PRNG implementation. - * - * Overview: A pseudo-random number generator (PRNG) generates a sequence - * of numbers that have a distribution close to the one expected - * for a sequence of truly random numbers. The NIST Special - * Publication 800-90A specifies several mechanisms to generate - * sequences of pseudo random numbers, including the HMAC-PRNG one - * which is based on HMAC. TinyCrypt implements HMAC-PRNG with - * certain modifications from the NIST SP 800-90A spec. - * - * Security: A cryptographically secure PRNG depends on the existence of an - * entropy source to provide a truly random seed as well as the - * security of the primitives used as the building blocks (HMAC and - * SHA256, for TinyCrypt). - * - * The NIST SP 800-90A standard tolerates a null personalization, - * while TinyCrypt requires a non-null personalization. This is - * because a personalization string (the host name concatenated - * with a time stamp, for example) is easily computed and might be - * the last line of defense against failure of the entropy source. - * - * Requires: - SHA-256 - * - HMAC - * - * Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the - * personalization data. - * - * 2) call tc_hmac_prng_reseed to process the seed and additional - * input. - * - * 3) call tc_hmac_prng_generate to out put the pseudo-random data. - */ - -#ifndef __TC_HMAC_PRNG_H__ -#define __TC_HMAC_PRNG_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TC_HMAC_PRNG_RESEED_REQ -1 - -struct tc_hmac_prng_struct { - /* the HMAC instance for this PRNG */ - struct tc_hmac_state_struct h; - /* the PRNG key */ - uint8_t key[TC_SHA256_DIGEST_SIZE]; - /* PRNG state */ - uint8_t v[TC_SHA256_DIGEST_SIZE]; - /* calls to tc_hmac_prng_generate left before re-seed */ - unsigned int countdown; -}; - -typedef struct tc_hmac_prng_struct *TCHmacPrng_t; - -/** - * @brief HMAC-PRNG initialization procedure - * Initializes prng with personalization, disables tc_hmac_prng_generate - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * prng == NULL, - * personalization == NULL, - * plen > MAX_PLEN - * @note Assumes: - personalization != NULL. - * The personalization is a platform unique string (e.g., the host - * name) and is the last line of defense against failure of the - * entropy source - * @warning NIST SP 800-90A specifies 3 items as seed material during - * initialization: entropy seed, personalization, and an optional - * nonce. TinyCrypts requires instead a non-null personalization - * (which is easily computed) and indirectly requires an entropy - * seed (since the reseed function is mandatorily called after - * init) - * @param prng IN/OUT -- the PRNG state to initialize - * @param personalization IN -- personalization string - * @param plen IN -- personalization length in bytes - */ -int tc_hmac_prng_init(TCHmacPrng_t prng, - const uint8_t *personalization, - unsigned int plen); - -/** - * @brief HMAC-PRNG reseed procedure - * Mixes seed into prng, enables tc_hmac_prng_generate - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * prng == NULL, - * seed == NULL, - * seedlen < MIN_SLEN, - * seendlen > MAX_SLEN, - * additional_input != (const uint8_t *) 0 && additionallen == 0, - * additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN - * @note Assumes:- tc_hmac_prng_init has been called for prng - * - seed has sufficient entropy. - * - * @param prng IN/OUT -- the PRNG state - * @param seed IN -- entropy to mix into the prng - * @param seedlen IN -- length of seed in bytes - * @param additional_input IN -- additional input to the prng - * @param additionallen IN -- additional input length in bytes - */ -int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed, - unsigned int seedlen, const uint8_t *additional_input, - unsigned int additionallen); - -/** - * @brief HMAC-PRNG generate procedure - * Generates outlen pseudo-random bytes into out buffer, updates prng - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed - * returns TC_CRYPTO_FAIL (0) if: - * out == NULL, - * prng == NULL, - * outlen == 0, - * outlen >= MAX_OUT - * @note Assumes tc_hmac_prng_init has been called for prng - * @param out IN/OUT -- buffer to receive output - * @param outlen IN -- size of out buffer in bytes - * @param prng IN/OUT -- the PRNG state - */ -int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_HMAC_PRNG_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h deleted file mode 100644 index af5e8baf79..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/sha256.h +++ /dev/null @@ -1,129 +0,0 @@ -/* sha256.h - TinyCrypt interface to a SHA-256 implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to a SHA-256 implementation. - * - * Overview: SHA-256 is a NIST approved cryptographic hashing algorithm - * specified in FIPS 180. A hash algorithm maps data of arbitrary - * size to data of fixed length. - * - * Security: SHA-256 provides 128 bits of security against collision attacks - * and 256 bits of security against pre-image attacks. SHA-256 does - * NOT behave like a random oracle, but it can be used as one if - * the string being hashed is prefix-free encoded before hashing. - * - * Usage: 1) call tc_sha256_init to initialize a struct - * tc_sha256_state_struct before hashing a new string. - * - * 2) call tc_sha256_update to hash the next string segment; - * tc_sha256_update can be called as many times as needed to hash - * all of the segments of a string; the order is important. - * - * 3) call tc_sha256_final to out put the digest from a hashing - * operation. - */ - -#ifndef __TC_SHA256_H__ -#define __TC_SHA256_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define TC_SHA256_BLOCK_SIZE (64) -#define TC_SHA256_DIGEST_SIZE (32) -#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4) - -struct tc_sha256_state_struct { - unsigned int iv[TC_SHA256_STATE_BLOCKS]; - uint64_t bits_hashed; - uint8_t leftover[TC_SHA256_BLOCK_SIZE]; - size_t leftover_offset; -}; - -typedef struct tc_sha256_state_struct *TCSha256State_t; - -/** - * @brief SHA256 initialization procedure - * Initializes s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if s == NULL - * @param s Sha256 state struct - */ -int tc_sha256_init(TCSha256State_t s); - -/** - * @brief SHA256 update procedure - * Hashes data_length bytes addressed by data into state s - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL, - * s->iv == NULL, - * data == NULL - * @note Assumes s has been initialized by tc_sha256_init - * @warning The state buffer 'leftover' is left in memory after processing - * If your application intends to have sensitive data in this - * buffer, remind to erase it after the data has been processed - * @param s Sha256 state struct - * @param data message to hash - * @param datalen length of message to hash - */ -int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen); - -/** - * @brief SHA256 final procedure - * Inserts the completed hash computation into digest - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * s == NULL, - * s->iv == NULL, - * digest == NULL - * @note Assumes: s has been initialized by tc_sha256_init - * digest points to at least TC_SHA256_DIGEST_SIZE bytes - * @warning The state buffer 'leftover' is left in memory after processing - * If your application intends to have sensitive data in this - * buffer, remind to erase it after the data has been processed - * @param digest unsigned eight bit integer - * @param Sha256 state struct - */ -int tc_sha256_final(uint8_t *digest, TCSha256State_t s); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_SHA256_H__ */ diff --git a/matter/mbedtls/tinycrypt/src/aes_decrypt.c b/matter/mbedtls/tinycrypt/src/aes_decrypt.c deleted file mode 100644 index 993a6180ce..0000000000 --- a/matter/mbedtls/tinycrypt/src/aes_decrypt.c +++ /dev/null @@ -1,164 +0,0 @@ -/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static const uint8_t inv_sbox[256] = { - 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, - 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, - 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, - 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, - 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, - 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, - 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, - 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, - 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, - 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, - 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, - 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, - 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, - 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, - 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, - 0x55, 0x21, 0x0c, 0x7d -}; - -int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k) -{ - return tc_aes128_set_encrypt_key(s, k); -} - -#define mult8(a)(_double_byte(_double_byte(_double_byte(a)))) -#define mult9(a)(mult8(a)^(a)) -#define multb(a)(mult8(a)^_double_byte(a)^(a)) -#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a)) -#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a)) - -static inline void mult_row_column(uint8_t *out, const uint8_t *in) -{ - out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]); - out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]); - out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]); - out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]); -} - -static inline void inv_mix_columns(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - mult_row_column(t, s); - mult_row_column(&t[Nb], s+Nb); - mult_row_column(&t[2*Nb], s+(2*Nb)); - mult_row_column(&t[3*Nb], s+(3*Nb)); - (void)_copy(s, sizeof(t), t, sizeof(t)); -} - -static inline void add_round_key(uint8_t *s, const unsigned int *k) -{ - s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); - s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); - s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); - s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); - s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); - s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); - s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); - s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); -} - -static inline void inv_sub_bytes(uint8_t *s) -{ - unsigned int i; - - for (i = 0; i < (Nb*Nk); ++i) { - s[i] = inv_sbox[s[i]]; - } -} - -/* - * This inv_shift_rows also implements the matrix flip required for - * inv_mix_columns, but performs it here to reduce the number of memory - * operations. - */ -static inline void inv_shift_rows(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7]; - t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11]; - t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15]; - t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3]; - (void)_copy(s, sizeof(t), t, sizeof(t)); -} - -int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) -{ - uint8_t state[Nk*Nb]; - unsigned int i; - - if (out == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (in == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)_copy(state, sizeof(state), in, sizeof(state)); - - add_round_key(state, s->words + Nb*Nr); - - for (i = Nr - 1; i > 0; --i) { - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, s->words + Nb*i); - inv_mix_columns(state); - } - - inv_shift_rows(state); - inv_sub_bytes(state); - add_round_key(state, s->words); - - (void)_copy(out, sizeof(state), state, sizeof(state)); - - /*zeroing out the state buffer */ - _set(state, TC_ZERO_BYTE, sizeof(state)); - - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/aes_encrypt.c b/matter/mbedtls/tinycrypt/src/aes_encrypt.c deleted file mode 100644 index 8991aee522..0000000000 --- a/matter/mbedtls/tinycrypt/src/aes_encrypt.c +++ /dev/null @@ -1,191 +0,0 @@ -/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static const uint8_t sbox[256] = { - 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, - 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, - 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, - 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, - 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, - 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, - 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, - 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, - 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, - 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, - 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, - 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, - 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, - 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, - 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, - 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, - 0xb0, 0x54, 0xbb, 0x16 -}; - -static inline unsigned int rotword(unsigned int a) -{ - return (((a) >> 24)|((a) << 8)); -} - -#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o)) -#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0)) - -int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k) -{ - const unsigned int rconst[11] = { - 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 - }; - unsigned int i; - unsigned int t; - - if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } else if (k == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - for (i = 0; i < Nk; ++i) { - s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) | - (k[Nb*i+2]<<8) | (k[Nb*i+3]); - } - - for (; i < (Nb * (Nr + 1)); ++i) { - t = s->words[i-1]; - if ((i % Nk) == 0) { - t = subword(rotword(t)) ^ rconst[i/Nk]; - } - s->words[i] = s->words[i-Nk] ^ t; - } - - return TC_CRYPTO_SUCCESS; -} - -static inline void add_round_key(uint8_t *s, const unsigned int *k) -{ - s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16); - s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]); - s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16); - s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]); - s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16); - s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]); - s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16); - s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]); -} - -static inline void sub_bytes(uint8_t *s) -{ - unsigned int i; - - for (i = 0; i < (Nb * Nk); ++i) { - s[i] = sbox[s[i]]; - } -} - -#define triple(a)(_double_byte(a)^(a)) - -static inline void mult_row_column(uint8_t *out, const uint8_t *in) -{ - out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3]; - out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3]; - out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]); - out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]); -} - -static inline void mix_columns(uint8_t *s) -{ - uint8_t t[Nb*Nk]; - - mult_row_column(t, s); - mult_row_column(&t[Nb], s+Nb); - mult_row_column(&t[2 * Nb], s + (2 * Nb)); - mult_row_column(&t[3 * Nb], s + (3 * Nb)); - (void) _copy(s, sizeof(t), t, sizeof(t)); -} - -/* - * This shift_rows also implements the matrix flip required for mix_columns, but - * performs it here to reduce the number of memory operations. - */ -static inline void shift_rows(uint8_t *s) -{ - uint8_t t[Nb * Nk]; - - t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15]; - t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3]; - t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7]; - t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11]; - (void) _copy(s, sizeof(t), t, sizeof(t)); -} - -int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s) -{ - uint8_t state[Nk*Nb]; - unsigned int i; - - if (out == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (in == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (s == (TCAesKeySched_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)_copy(state, sizeof(state), in, sizeof(state)); - add_round_key(state, s->words); - - for (i = 0; i < (Nr - 1); ++i) { - sub_bytes(state); - shift_rows(state); - mix_columns(state); - add_round_key(state, s->words + Nb*(i+1)); - } - - sub_bytes(state); - shift_rows(state); - add_round_key(state, s->words + Nb*(i+1)); - - (void)_copy(out, sizeof(state), state, sizeof(state)); - - /* zeroing out the state buffer */ - _set(state, TC_ZERO_BYTE, sizeof(state)); - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/cbc_mode.c b/matter/mbedtls/tinycrypt/src/cbc_mode.c deleted file mode 100644 index 62d7879ebd..0000000000 --- a/matter/mbedtls/tinycrypt/src/cbc_mode.c +++ /dev/null @@ -1,114 +0,0 @@ -/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - unsigned int n, m; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (const uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - (inlen % TC_AES_BLOCK_SIZE) != 0 || - (outlen % TC_AES_BLOCK_SIZE) != 0 || - outlen != inlen + TC_AES_BLOCK_SIZE) { - return TC_CRYPTO_FAIL; - } - - /* copy iv to the buffer */ - (void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); - /* copy iv to the output buffer */ - (void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE); - out += TC_AES_BLOCK_SIZE; - - for (n = m = 0; n < inlen; ++n) { - buffer[m++] ^= *in++; - if (m == TC_AES_BLOCK_SIZE) { - (void)tc_aes_encrypt(buffer, buffer, sched); - (void)_copy(out, TC_AES_BLOCK_SIZE, - buffer, TC_AES_BLOCK_SIZE); - out += TC_AES_BLOCK_SIZE; - m = 0; - } - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, const uint8_t *iv, - const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - const uint8_t *p; - unsigned int n, m; - - /* sanity check the inputs */ - if (out == (uint8_t *) 0 || - in == (const uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - (inlen % TC_AES_BLOCK_SIZE) != 0 || - (outlen % TC_AES_BLOCK_SIZE) != 0 || - outlen != inlen - TC_AES_BLOCK_SIZE) { - return TC_CRYPTO_FAIL; - } - - /* - * Note that in == iv + ciphertext, i.e. the iv and the ciphertext are - * contiguous. This allows for a very efficient decryption algorithm - * that would not otherwise be possible. - */ - p = iv; - for (n = m = 0; n < inlen; ++n) { - if ((n % TC_AES_BLOCK_SIZE) == 0) { - (void)tc_aes_decrypt(buffer, in, sched); - in += TC_AES_BLOCK_SIZE; - m = 0; - } - *out++ = buffer[m++] ^ *p++; - } - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/ccm_mode.c b/matter/mbedtls/tinycrypt/src/ccm_mode.c deleted file mode 100644 index 929adac630..0000000000 --- a/matter/mbedtls/tinycrypt/src/ccm_mode.c +++ /dev/null @@ -1,266 +0,0 @@ -/* ccm_mode.c - TinyCrypt implementation of CCM mode */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#include - -int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce, - unsigned int nlen, unsigned int mlen) -{ - - /* input sanity check: */ - if (c == (TCCcmMode_t) 0 || - sched == (TCAesKeySched_t) 0 || - nonce == (uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } else if (nlen != 13) { - return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/ - } else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) { - return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/ - } - - c->mlen = mlen; - c->sched = sched; - c->nonce = nonce; - - return TC_CRYPTO_SUCCESS; -} - -/** - * Variation of CBC-MAC mode used in CCM. - */ -static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen, - unsigned int flag, TCAesKeySched_t sched) -{ - - unsigned int i; - - if (flag > 0) { - T[0] ^= (uint8_t)(dlen >> 8); - T[1] ^= (uint8_t)(dlen); - dlen += 2; i = 2; - } else { - i = 0; - } - - while (i < dlen) { - T[i++ % (Nb * Nk)] ^= *data++; - if (((i % (Nb * Nk)) == 0) || dlen == i) { - (void) tc_aes_encrypt(T, T, sched); - } - } -} - -/** - * Variation of CTR mode used in CCM. - * The CTR mode used by CCM is slightly different than the conventional CTR - * mode (the counter is increased before encryption, instead of after - * encryption). Besides, it is assumed that the counter is stored in the last - * 2 bytes of the nonce. - */ -static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - uint8_t nonce[TC_AES_BLOCK_SIZE]; - uint16_t block_num; - unsigned int i; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (uint8_t *) 0 || - ctr == (uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - outlen != inlen) { - return TC_CRYPTO_FAIL; - } - - /* copy the counter to the nonce */ - (void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); - - /* select the last 2 bytes of the nonce to be incremented */ - block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15])); - for (i = 0; i < inlen; ++i) { - if ((i % (TC_AES_BLOCK_SIZE)) == 0) { - block_num++; - nonce[14] = (uint8_t)(block_num >> 8); - nonce[15] = (uint8_t)(block_num); - if (!tc_aes_encrypt(buffer, nonce, sched)) { - return TC_CRYPTO_FAIL; - } - } - /* update the output */ - *out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++; - } - - /* update the counter */ - ctr[14] = nonce[14]; ctr[15] = nonce[15]; - - return TC_CRYPTO_SUCCESS; -} - -int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c) -{ - - /* input sanity check: */ - if ((out == (uint8_t *) 0) || - (c == (TCCcmMode_t) 0) || - ((plen > 0) && (payload == (uint8_t *) 0)) || - ((alen > 0) && (associated_data == (uint8_t *) 0)) || - (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ - (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ - (olen < (plen + c->mlen))) { /* invalid output buffer size */ - return TC_CRYPTO_FAIL; - } - - uint8_t b[Nb * Nk]; - uint8_t tag[Nb * Nk]; - unsigned int i; - - /* GENERATING THE AUTHENTICATION TAG: */ - - /* formatting the sequence b for authentication: */ - b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1); - for (i = 1; i <= 13; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = (uint8_t)(plen >> 8); - b[15] = (uint8_t)(plen); - - /* computing the authentication tag using cbc-mac: */ - (void) tc_aes_encrypt(tag, b, c->sched); - if (alen > 0) { - ccm_cbc_mac(tag, associated_data, alen, 1, c->sched); - } - if (plen > 0) { - ccm_cbc_mac(tag, payload, plen, 0, c->sched); - } - - /* ENCRYPTION: */ - - /* formatting the sequence b for encryption: */ - b[0] = 1; /* q - 1 = 2 - 1 = 1 */ - b[14] = b[15] = TC_ZERO_BYTE; - - /* encrypting payload using ctr mode: */ - ccm_ctr_mode(out, plen, payload, plen, b, c->sched); - - b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/ - - /* encrypting b and adding the tag to the output: */ - (void) tc_aes_encrypt(b, b, c->sched); - out += plen; - for (i = 0; i < c->mlen; ++i) { - *out++ = tag[i] ^ b[i]; - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen, - const uint8_t *associated_data, - unsigned int alen, const uint8_t *payload, - unsigned int plen, TCCcmMode_t c) -{ - - /* input sanity check: */ - if ((out == (uint8_t *) 0) || - (c == (TCCcmMode_t) 0) || - ((plen > 0) && (payload == (uint8_t *) 0)) || - ((alen > 0) && (associated_data == (uint8_t *) 0)) || - (alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */ - (plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */ - (olen < plen - c->mlen)) { /* invalid output buffer size */ - return TC_CRYPTO_FAIL; - } - - uint8_t b[Nb * Nk]; - uint8_t tag[Nb * Nk]; - unsigned int i; - - /* DECRYPTION: */ - - /* formatting the sequence b for decryption: */ - b[0] = 1; /* q - 1 = 2 - 1 = 1 */ - for (i = 1; i < 14; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */ - - /* decrypting payload using ctr mode: */ - ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched); - - b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */ - - /* encrypting b and restoring the tag from input: */ - (void) tc_aes_encrypt(b, b, c->sched); - for (i = 0; i < c->mlen; ++i) { - tag[i] = *(payload + plen - c->mlen + i) ^ b[i]; - } - - /* VERIFYING THE AUTHENTICATION TAG: */ - - /* formatting the sequence b for authentication: */ - b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1); - for (i = 1; i < 14; ++i) { - b[i] = c->nonce[i - 1]; - } - b[14] = (uint8_t)((plen - c->mlen) >> 8); - b[15] = (uint8_t)(plen - c->mlen); - - /* computing the authentication tag using cbc-mac: */ - (void) tc_aes_encrypt(b, b, c->sched); - if (alen > 0) { - ccm_cbc_mac(b, associated_data, alen, 1, c->sched); - } - if (plen > 0) { - ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched); - } - - /* comparing the received tag and the computed one: */ - if (_compare(b, tag, c->mlen) == 0) { - return TC_CRYPTO_SUCCESS; - } else { - /* erase the decrypted buffer in case of mac validation failure: */ - _set(out, 0, plen - c->mlen); - return TC_CRYPTO_FAIL; - } -} diff --git a/matter/mbedtls/tinycrypt/src/cmac_mode.c b/matter/mbedtls/tinycrypt/src/cmac_mode.c deleted file mode 100644 index 96d147e809..0000000000 --- a/matter/mbedtls/tinycrypt/src/cmac_mode.c +++ /dev/null @@ -1,254 +0,0 @@ -/* cmac_mode.c - TinyCrypt CMAC mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* max number of calls until change the key (2^48).*/ -const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); - -/* - * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte - * array with byte 0 the most significant and byte 15 the least significant. - * High bit carry reduction is based on the primitive polynomial - * - * X^128 + X^7 + X^2 + X + 1, - * - * which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed, - * since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since - * addition of polynomials with coefficients in Z/Z(2) is just XOR, we can - * add X^128 to both sides to get - * - * X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1) - * - * and the coefficients of the polynomial on the right hand side form the - * string 1000 0111 = 0x87, which is the value of gf_wrap. - * - * This gets used in the following way. Doubling in GF(2^128) is just a left - * shift by 1 bit, except when the most significant bit is 1. In the latter - * case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit - * that overflows beyond 128 bits can be replaced by addition of - * X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition - * in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87 - * into the low order byte after a left shift when the starting high order - * bit is 1. - */ -const unsigned char gf_wrap = 0x87; - -/* - * assumes: out != NULL and points to a GF(2^n) value to receive the - * doubled value; - * in != NULL and points to a 16 byte GF(2^n) value - * to double; - * the in and out buffers do not overlap. - * effects: doubles the GF(2^n) value pointed to by "in" and places - * the result in the GF(2^n) value pointed to by "out." - */ -void gf_double(uint8_t *out, uint8_t *in) -{ - - /* start with low order byte */ - uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1); - - /* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */ - uint8_t carry = (in[0] >> 7) ? gf_wrap : 0; - - out += (TC_AES_BLOCK_SIZE - 1); - for (;;) { - *out-- = (*x << 1) ^ carry; - if (x == in) { - break; - } - carry = *x-- >> 7; - } -} - -int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched) -{ - - /* input sanity check: */ - if (s == (TCCmacState_t) 0 || - key == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - /* put s into a known state */ - _set(s, 0, sizeof(*s)); - s->sched = sched; - - /* configure the encryption key used by the underlying block cipher */ - tc_aes128_set_encrypt_key(s->sched, key); - - /* compute s->K1 and s->K2 from s->iv using s->keyid */ - _set(s->iv, 0, TC_AES_BLOCK_SIZE); - tc_aes_encrypt(s->iv, s->iv, s->sched); - gf_double (s->K1, s->iv); - gf_double (s->K2, s->K1); - - /* reset s->iv to 0 in case someone wants to compute now */ - tc_cmac_init(s); - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_erase(TCCmacState_t s) -{ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* destroy the current state */ - _set(s, 0, sizeof(*s)); - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_init(TCCmacState_t s) -{ - /* input sanity check: */ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - /* CMAC starts with an all zero initialization vector */ - _set(s->iv, 0, TC_AES_BLOCK_SIZE); - - /* and the leftover buffer is empty */ - _set(s->leftover, 0, TC_AES_BLOCK_SIZE); - s->leftover_offset = 0; - - /* Set countdown to max number of calls allowed before re-keying: */ - s->countdown = MAX_CALLS; - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length) -{ - unsigned int i; - - /* input sanity check: */ - if (s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - if (data_length == 0) { - return TC_CRYPTO_SUCCESS; - } - if (data == (const uint8_t *) 0) { - return TC_CRYPTO_FAIL; - } - - if (s->countdown == 0) { - return TC_CRYPTO_FAIL; - } - - s->countdown--; - - if (s->leftover_offset > 0) { - /* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */ - size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset; - - if (data_length < remaining_space) { - /* still not enough data to encrypt this time either */ - _copy(&s->leftover[s->leftover_offset], data_length, data, data_length); - s->leftover_offset += data_length; - return TC_CRYPTO_SUCCESS; - } - /* leftover block is now full; encrypt it first */ - _copy(&s->leftover[s->leftover_offset], - remaining_space, - data, - remaining_space); - data_length -= remaining_space; - data += remaining_space; - s->leftover_offset = 0; - - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= s->leftover[i]; - } - tc_aes_encrypt(s->iv, s->iv, s->sched); - } - - /* CBC encrypt each (except the last) of the data blocks */ - while (data_length > TC_AES_BLOCK_SIZE) { - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= data[i]; - } - tc_aes_encrypt(s->iv, s->iv, s->sched); - data += TC_AES_BLOCK_SIZE; - data_length -= TC_AES_BLOCK_SIZE; - } - - if (data_length > 0) { - /* save leftover data for next time */ - _copy(s->leftover, data_length, data, data_length); - s->leftover_offset = data_length; - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_cmac_final(uint8_t *tag, TCCmacState_t s) -{ - uint8_t *k; - unsigned int i; - - /* input sanity check: */ - if (tag == (uint8_t *) 0 || - s == (TCCmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - if (s->leftover_offset == TC_AES_BLOCK_SIZE) { - /* the last message block is a full-sized block */ - k = (uint8_t *) s->K1; - } else { - /* the final message block is not a full-sized block */ - size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset; - - _set(&s->leftover[s->leftover_offset], 0, remaining); - s->leftover[s->leftover_offset] = TC_CMAC_PADDING; - k = (uint8_t *) s->K2; - } - for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) { - s->iv[i] ^= s->leftover[i] ^ k[i]; - } - - tc_aes_encrypt(tag, s->iv, s->sched); - - /* erasing state: */ - tc_cmac_erase(s); - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/ctr_mode.c b/matter/mbedtls/tinycrypt/src/ctr_mode.c deleted file mode 100644 index 1dfb92dfec..0000000000 --- a/matter/mbedtls/tinycrypt/src/ctr_mode.c +++ /dev/null @@ -1,85 +0,0 @@ -/* ctr_mode.c - TinyCrypt CTR mode implementation */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, - unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) -{ - - uint8_t buffer[TC_AES_BLOCK_SIZE]; - uint8_t nonce[TC_AES_BLOCK_SIZE]; - unsigned int block_num; - unsigned int i; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - in == (uint8_t *) 0 || - ctr == (uint8_t *) 0 || - sched == (TCAesKeySched_t) 0 || - inlen == 0 || - outlen == 0 || - outlen != inlen) { - return TC_CRYPTO_FAIL; - } - - /* copy the ctr to the nonce */ - (void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce)); - - /* select the last 4 bytes of the nonce to be incremented */ - block_num = (nonce[12] << 24) | (nonce[13] << 16) | - (nonce[14] << 8) | (nonce[15]); - for (i = 0; i < inlen; ++i) { - if ((i % (TC_AES_BLOCK_SIZE)) == 0) { - /* encrypt data using the current nonce */ - if (tc_aes_encrypt(buffer, nonce, sched)) { - block_num++; - nonce[12] = (uint8_t)(block_num >> 24); - nonce[13] = (uint8_t)(block_num >> 16); - nonce[14] = (uint8_t)(block_num >> 8); - nonce[15] = (uint8_t)(block_num); - } else { - return TC_CRYPTO_FAIL; - } - } - /* update the output */ - *out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++; - } - - /* update the counter */ - ctr[12] = nonce[12]; ctr[13] = nonce[13]; - ctr[14] = nonce[14]; ctr[15] = nonce[15]; - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/ctr_prng.c b/matter/mbedtls/tinycrypt/src/ctr_prng.c deleted file mode 100644 index cac2cc41d6..0000000000 --- a/matter/mbedtls/tinycrypt/src/ctr_prng.c +++ /dev/null @@ -1,283 +0,0 @@ -/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */ - -/* - * Copyright (c) 2016, Chris Morrison - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* - * This PRNG is based on the CTR_DRBG described in Recommendation for Random - * Number Generation Using Deterministic Random Bit Generators, - * NIST SP 800-90A Rev. 1. - * - * Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps - * described in that document. - * - */ - -/** - * @brief Array incrementer - * Treats the supplied array as one contiguous number (MSB in arr[0]), and - * increments it by one - * @return none - * @param arr IN/OUT -- array to be incremented - * @param len IN -- size of arr in bytes - */ -static void arrInc(uint8_t arr[], unsigned int len) -{ - unsigned int i; - if (0 != arr) { - for (i = len; i > 0U; i--) { - if (++arr[i-1] != 0U) { - break; - } - } - } -} - -/** - * @brief CTR PRNG update - * Updates the internal state of supplied the CTR PRNG context - * increments it by one - * @return none - * @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long - * @param ctx IN/OUT -- CTR PRNG state - * @param providedData IN -- data used when updating the internal state - */ -static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData) -{ - if (0 != ctx) { - /* 10.2.1.2 step 1 */ - uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - unsigned int len = 0U; - - /* 10.2.1.2 step 2 */ - while (len < sizeof temp) { - unsigned int blocklen = sizeof(temp) - len; - uint8_t output_block[TC_AES_BLOCK_SIZE]; - - /* 10.2.1.2 step 2.1 */ - arrInc(ctx->V, sizeof ctx->V); - - /* 10.2.1.2 step 2.2 */ - if (blocklen > TC_AES_BLOCK_SIZE) { - blocklen = TC_AES_BLOCK_SIZE; - } - (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); - - /* 10.2.1.2 step 2.3/step 3 */ - memcpy(&(temp[len]), output_block, blocklen); - - len += blocklen; - } - - /* 10.2.1.2 step 4 */ - if (0 != providedData) { - unsigned int i; - for (i = 0U; i < sizeof temp; i++) { - temp[i] ^= providedData[i]; - } - } - - /* 10.2.1.2 step 5 */ - (void)tc_aes128_set_encrypt_key(&ctx->key, temp); - - /* 10.2.1.2 step 6 */ - memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE); - } -} - -int tc_ctr_prng_init(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const personalization, - unsigned int pLen) -{ - int result = TC_CRYPTO_FAIL; - unsigned int i; - uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U}; - - if (0 != personalization) { - /* 10.2.1.3.1 step 1 */ - unsigned int len = pLen; - if (len > sizeof personalization_buf) { - len = sizeof personalization_buf; - } - - /* 10.2.1.3.1 step 2 */ - memcpy(personalization_buf, personalization, len); - } - - if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) { - /* 10.2.1.3.1 step 3 */ - memcpy(seed_material, entropy, sizeof seed_material); - for (i = 0U; i < sizeof seed_material; i++) { - seed_material[i] ^= personalization_buf[i]; - } - - /* 10.2.1.3.1 step 4 */ - (void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr); - - /* 10.2.1.3.1 step 5 */ - memset(ctx->V, 0x00, sizeof ctx->V); - - /* 10.2.1.3.1 step 6 */ - tc_ctr_prng_update(ctx, seed_material); - - /* 10.2.1.3.1 step 7 */ - ctx->reseedCount = 1U; - - result = TC_CRYPTO_SUCCESS; - } - return result; -} - -int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx, - uint8_t const * const entropy, - unsigned int entropyLen, - uint8_t const * const additional_input, - unsigned int additionallen) -{ - unsigned int i; - int result = TC_CRYPTO_FAIL; - uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; - - if (0 != additional_input) { - /* 10.2.1.4.1 step 1 */ - unsigned int len = additionallen; - if (len > sizeof additional_input_buf) { - len = sizeof additional_input_buf; - } - - /* 10.2.1.4.1 step 2 */ - memcpy(additional_input_buf, additional_input, len); - } - - unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE; - if ((0 != ctx) && (entropyLen >= seedlen)) { - /* 10.2.1.4.1 step 3 */ - memcpy(seed_material, entropy, sizeof seed_material); - for (i = 0U; i < sizeof seed_material; i++) { - seed_material[i] ^= additional_input_buf[i]; - } - - /* 10.2.1.4.1 step 4 */ - tc_ctr_prng_update(ctx, seed_material); - - /* 10.2.1.4.1 step 5 */ - ctx->reseedCount = 1U; - - result = TC_CRYPTO_SUCCESS; - } - return result; -} - -int tc_ctr_prng_generate(TCCtrPrng_t * const ctx, - uint8_t const * const additional_input, - unsigned int additionallen, - uint8_t * const out, - unsigned int outlen) -{ - /* 2^48 - see section 10.2.1 */ - static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL; - - /* 2^19 bits - see section 10.2.1 */ - static const unsigned int MAX_BYTES_PER_REQ = 65536U; - - unsigned int result = TC_CRYPTO_FAIL; - - if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) { - /* 10.2.1.5.1 step 1 */ - if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) { - result = TC_CTR_PRNG_RESEED_REQ; - } else { - uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U}; - if (0 != additional_input) { - /* 10.2.1.5.1 step 2 */ - unsigned int len = additionallen; - if (len > sizeof additional_input_buf) { - len = sizeof additional_input_buf; - } - memcpy(additional_input_buf, additional_input, len); - tc_ctr_prng_update(ctx, additional_input_buf); - } - - /* 10.2.1.5.1 step 3 - implicit */ - - /* 10.2.1.5.1 step 4 */ - unsigned int len = 0U; - while (len < outlen) { - unsigned int blocklen = outlen - len; - uint8_t output_block[TC_AES_BLOCK_SIZE]; - - /* 10.2.1.5.1 step 4.1 */ - arrInc(ctx->V, sizeof ctx->V); - - /* 10.2.1.5.1 step 4.2 */ - (void)tc_aes_encrypt(output_block, ctx->V, &ctx->key); - - /* 10.2.1.5.1 step 4.3/step 5 */ - if (blocklen > TC_AES_BLOCK_SIZE) { - blocklen = TC_AES_BLOCK_SIZE; - } - memcpy(&(out[len]), output_block, blocklen); - - len += blocklen; - } - - /* 10.2.1.5.1 step 6 */ - tc_ctr_prng_update(ctx, additional_input_buf); - - /* 10.2.1.5.1 step 7 */ - ctx->reseedCount++; - - /* 10.2.1.5.1 step 8 */ - result = TC_CRYPTO_SUCCESS; - } - } - - return result; -} - -void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx) -{ - if (0 != ctx) { - memset(ctx->key.words, 0x00, sizeof ctx->key.words); - memset(ctx->V, 0x00, sizeof ctx->V); - ctx->reseedCount = 0U; - } -} - - - - diff --git a/matter/mbedtls/tinycrypt/src/error.c b/matter/mbedtls/tinycrypt/src/error.c deleted file mode 100644 index 763835a371..0000000000 --- a/matter/mbedtls/tinycrypt/src/error.c +++ /dev/null @@ -1,1064 +0,0 @@ -/* - * Error message information - * - * 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. - */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its - *contributors may be used to endorse or promote products derived from this - *software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "common.h" - -#include "mbedtls/error.h" - -#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) - -#if defined(MBEDTLS_ERROR_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#endif - -#include -#include - -#if defined(MBEDTLS_AES_C) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - -#if defined(MBEDTLS_ARIA_C) -#include "mbedtls/aria.h" -#endif - -#if defined(MBEDTLS_ASN1_PARSE_C) -#include "mbedtls/asn1.h" -#endif - -#if defined(MBEDTLS_BASE64_C) -#include "mbedtls/base64.h" -#endif - -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif - -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#include "mbedtls/camellia.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CHACHA20_C) -#include "mbedtls/chacha20.h" -#endif - -#if defined(MBEDTLS_CHACHAPOLY_C) -#include "mbedtls/chachapoly.h" -#endif - -#if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher.h" -#endif - -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -#if defined(MBEDTLS_DHM_C) -#include "mbedtls/dhm.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ENTROPY_C) -#include "mbedtls/entropy.h" -#endif - -#if defined(MBEDTLS_ERROR_C) -#include "mbedtls/error.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_HKDF_C) -#include "mbedtls/hkdf.h" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) -#include "mbedtls/hmac_drbg.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_MD2_C) -#include "mbedtls/md2.h" -#endif - -#if defined(MBEDTLS_MD4_C) -#include "mbedtls/md4.h" -#endif - -#if defined(MBEDTLS_MD5_C) -#include "mbedtls/md5.h" -#endif - -#if defined(MBEDTLS_NET_C) -#include "mbedtls/net_sockets.h" -#endif - -#if defined(MBEDTLS_OID_C) -#include "mbedtls/oid.h" -#endif - -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#endif - -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#endif - -#if defined(MBEDTLS_POLY1305_C) -#include "mbedtls/poly1305.h" -#endif - -#if defined(MBEDTLS_RIPEMD160_C) -#include "mbedtls/ripemd160.h" -#endif - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "mbedtls/sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "mbedtls/sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "mbedtls/sha512.h" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) -#include "mbedtls/ssl.h" -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" -#endif - -#if defined(MBEDTLS_XTEA_C) -#include "mbedtls/xtea.h" -#endif - -#if defined(TINYCRYPT_PRIMITIVES) -#include "tinycrypt/ecc.h" -#endif - -const char *mbedtls_high_level_strerr(int error_code) { - int high_level_error_code; - - if (error_code < 0) - error_code = -error_code; - - /* Extract the high-level part from the error code. */ - high_level_error_code = error_code & 0xFF80; - - switch (high_level_error_code) { - /* Begin Auto-Generated Code. */ -#if defined(MBEDTLS_CIPHER_C) - case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): - return ("CIPHER - The selected feature is not available"); - case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): - return ("CIPHER - Bad input parameters"); - case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): - return ("CIPHER - Failed to allocate memory"); - case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): - return ("CIPHER - Input data contains invalid padding and is rejected"); - case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): - return ("CIPHER - Decryption of block requires a full block"); - case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): - return ("CIPHER - Authentication failed (for AEAD modes)"); - case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): - return ( - "CIPHER - The context is invalid. For example, because it was freed"); - case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED): - return ("CIPHER - Cipher hardware accelerator failed"); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_DHM_C) - case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): - return ("DHM - Bad input parameters"); - case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): - return ("DHM - Reading of the DHM parameters failed"); - case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): - return ("DHM - Making of the DHM parameters failed"); - case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): - return ("DHM - Reading of the public values failed"); - case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): - return ("DHM - Making of the public value failed"); - case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): - return ("DHM - Calculation of the DHM secret failed"); - case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): - return ("DHM - The ASN.1 data is not formatted correctly"); - case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): - return ("DHM - Allocation of memory failed"); - case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): - return ("DHM - Read or write of file failed"); - case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED): - return ("DHM - DHM hardware accelerator failed"); - case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): - return ("DHM - Setting the modulus and generator failed"); -#endif /* MBEDTLS_DHM_C */ - -#if defined(MBEDTLS_ECP_C) - case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): - return ("ECP - Bad input parameters to function"); - case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): - return ("ECP - The buffer is too small to write to"); - case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): - return ("ECP - The requested feature is not available, for example, the " - "requested curve is not supported"); - case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): - return ("ECP - The signature is not valid"); - case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): - return ("ECP - Memory allocation failed"); - case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): - return ("ECP - Generation of random value, such as ephemeral key, failed"); - case -(MBEDTLS_ERR_ECP_INVALID_KEY): - return ("ECP - Invalid private or public key"); - case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): - return ( - "ECP - The buffer contains a valid signature followed by more data"); - case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED): - return ("ECP - The ECP hardware accelerator failed"); - case -(MBEDTLS_ERR_ECP_IN_PROGRESS): - return ("ECP - Operation in progress, call again with the same parameters " - "to continue"); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_MD_C) - case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): - return ("MD - The selected feature is not available"); - case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): - return ("MD - Bad input parameters to function"); - case -(MBEDTLS_ERR_MD_ALLOC_FAILED): - return ("MD - Failed to allocate memory"); - case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): - return ("MD - Opening or reading of file failed"); - case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED): - return ("MD - MD hardware accelerator failed"); -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): - return ("PEM - No PEM header or footer found"); - case -(MBEDTLS_ERR_PEM_INVALID_DATA): - return ("PEM - PEM string is not as expected"); - case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): - return ("PEM - Failed to allocate memory"); - case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): - return ("PEM - RSA IV is not in hex-format"); - case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): - return ("PEM - Unsupported key encryption algorithm"); - case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): - return ("PEM - Private key password can't be empty"); - case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): - return ("PEM - Given private key password does not allow for correct " - "decryption"); - case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): - return ("PEM - Unavailable feature, e.g. hashing/encryption combination"); - case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): - return ("PEM - Bad input parameters to function"); -#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ - -#if defined(MBEDTLS_PK_C) - case -(MBEDTLS_ERR_PK_ALLOC_FAILED): - return ("PK - Memory allocation failed"); - case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): - return ("PK - Type mismatch, eg attempt to encrypt with an ECDSA key"); - case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): - return ("PK - Bad input parameters to function"); - case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): - return ("PK - Read/write of file failed"); - case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): - return ("PK - Unsupported key version"); - case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): - return ("PK - Invalid key tag or value"); - case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): - return ( - "PK - Key algorithm is unsupported (only RSA and EC are supported)"); - case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): - return ("PK - Private key password can't be empty"); - case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): - return ("PK - Given private key password does not allow for correct " - "decryption"); - case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): - return ("PK - The pubkey tag or value is invalid (only RSA and EC are " - "supported)"); - case -(MBEDTLS_ERR_PK_INVALID_ALG): - return ("PK - The algorithm tag or value is invalid"); - case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): - return ( - "PK - Elliptic curve is unsupported (only NIST curves are supported)"); - case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): - return ("PK - Unavailable feature, e.g. RSA disabled for RSA key"); - case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): - return ("PK - The buffer contains a valid signature followed by more data"); - case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED): - return ("PK - PK hardware accelerator failed"); -#endif /* MBEDTLS_PK_C */ - -#if defined(MBEDTLS_PKCS12_C) - case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): - return ("PKCS12 - Bad input parameters to function"); - case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): - return ( - "PKCS12 - Feature not available, e.g. unsupported encryption scheme"); - case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): - return ("PKCS12 - PBE ASN.1 data not as expected"); - case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): - return ("PKCS12 - Given private key password does not allow for correct " - "decryption"); -#endif /* MBEDTLS_PKCS12_C */ - -#if defined(MBEDTLS_PKCS5_C) - case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): - return ("PKCS5 - Bad input parameters to function"); - case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): - return ("PKCS5 - Unexpected ASN.1 data"); - case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): - return ("PKCS5 - Requested encryption or digest alg not available"); - case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): - return ("PKCS5 - Given private key password does not allow for correct " - "decryption"); -#endif /* MBEDTLS_PKCS5_C */ - -#if defined(MBEDTLS_RSA_C) - case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): - return ("RSA - Bad input parameters to function"); - case -(MBEDTLS_ERR_RSA_INVALID_PADDING): - return ("RSA - Input data contains invalid padding and is rejected"); - case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): - return ("RSA - Something failed during generation of a key"); - case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): - return ("RSA - Key failed to pass the validity check of the library"); - case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): - return ("RSA - The public key operation failed"); - case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): - return ("RSA - The private key operation failed"); - case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): - return ("RSA - The PKCS#1 verification failed"); - case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): - return ("RSA - The output buffer for decryption is not large enough"); - case -(MBEDTLS_ERR_RSA_RNG_FAILED): - return ("RSA - The random generator failed to generate non-zeros"); - case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION): - return ( - "RSA - The implementation does not offer the requested operation, for " - "example, because of security violations or lack of functionality"); - case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED): - return ("RSA - RSA hardware accelerator failed"); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_SSL_TLS_C) - case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): - return ("SSL - The requested feature is not available"); - case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): - return ("SSL - Bad input parameters to function"); - case -(MBEDTLS_ERR_SSL_INVALID_MAC): - return ("SSL - Verification of the message MAC failed"); - case -(MBEDTLS_ERR_SSL_INVALID_RECORD): - return ("SSL - An invalid SSL record was received"); - case -(MBEDTLS_ERR_SSL_CONN_EOF): - return ("SSL - The connection indicated an EOF"); - case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER): - return ("SSL - An unknown cipher was received"); - case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN): - return ("SSL - The server has no ciphersuites in common with the client"); - case -(MBEDTLS_ERR_SSL_NO_RNG): - return ("SSL - No RNG was provided to the SSL module"); - case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): - return ("SSL - No client certification received from the client, but " - "required by the authentication mode"); - case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE): - return ("SSL - Our own certificate(s) is/are too large to send in an SSL " - "message"); - case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED): - return ("SSL - The own certificate is not set, but needed by the server"); - case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): - return ( - "SSL - The own private key or pre-shared key is not set, but needed"); - case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): - return ("SSL - No CA Chain is set, but required to operate"); - case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): - return ("SSL - An unexpected message was received from our peer"); - case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): - return ("SSL - A fatal alert message was received from our peer"); - case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED): - return ("SSL - Verification of our peer failed"); - case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): - return ( - "SSL - The peer notified us that the connection is going to be closed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO): - return ("SSL - Processing of the ClientHello handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO): - return ("SSL - Processing of the ServerHello handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE): - return ("SSL - Processing of the Certificate handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST): - return ( - "SSL - Processing of the CertificateRequest handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE): - return ( - "SSL - Processing of the ServerKeyExchange handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE): - return ("SSL - Processing of the ServerHelloDone handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE): - return ( - "SSL - Processing of the ClientKeyExchange handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP): - return ("SSL - Processing of the ClientKeyExchange handshake message " - "failed in DHM / ECDH Read Public"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS): - return ("SSL - Processing of the ClientKeyExchange handshake message " - "failed in DHM / ECDH Calculate Secret"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY): - return ( - "SSL - Processing of the CertificateVerify handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC): - return ( - "SSL - Processing of the ChangeCipherSpec handshake message failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED): - return ("SSL - Processing of the Finished handshake message failed"); - case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): - return ("SSL - Memory allocation failed"); - case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): - return ("SSL - Hardware acceleration function returned with error"); - case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): - return ("SSL - Hardware acceleration function skipped / left alone data"); - case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED): - return ("SSL - Processing of the compression / decompression failed"); - case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION): - return ("SSL - Handshake protocol not within min/max boundaries"); - case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET): - return ( - "SSL - Processing of the NewSessionTicket handshake message failed"); - case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): - return ("SSL - Session ticket has expired"); - case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): - return ("SSL - Public key type mismatch (eg, asked for RSA key exchange " - "and presented EC key)"); - case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): - return ("SSL - Unknown identity received (eg, PSK identity)"); - case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): - return ( - "SSL - Internal error (eg, unexpected failure in lower-level module)"); - case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): - return ("SSL - A counter would wrap (eg, too many messages exchanged)"); - case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): - return ("SSL - Unexpected message at ServerHello in renegotiation"); - case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): - return ("SSL - DTLS client must retry for hello verification"); - case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): - return ("SSL - A buffer is too small to receive or write a message"); - case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE): - return ("SSL - None of the common ciphersuites is usable (eg, no suitable " - "certificate, see debug messages)"); - case -(MBEDTLS_ERR_SSL_WANT_READ): - return ("SSL - No data of requested type currently available on underlying " - "transport"); - case -(MBEDTLS_ERR_SSL_WANT_WRITE): - return ("SSL - Connection requires a write call"); - case -(MBEDTLS_ERR_SSL_TIMEOUT): - return ("SSL - The operation timed out"); - case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): - return ("SSL - The client initiated a reconnect from the same port"); - case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): - return ("SSL - Record header looks valid but is not expected"); - case -(MBEDTLS_ERR_SSL_NON_FATAL): - return ("SSL - The alert message received indicates a non-fatal error"); - case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH): - return ("SSL - Couldn't set the hash for verifying CertificateVerify"); - case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): - return ("SSL - Internal-only message signaling that further " - "message-processing should be done"); - case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): - return ("SSL - The asynchronous operation is not completed yet"); - case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): - return ( - "SSL - Internal-only message signaling that a message arrived early"); - case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): - return ( - "SSL - An encrypted DTLS-frame with an unexpected CID was received"); - case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): - return ("SSL - An operation failed due to an unexpected version or " - "configuration"); - case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): - return ("SSL - A cryptographic operation is in progress. Try again later"); - case -(MBEDTLS_ERR_SSL_BAD_CONFIG): - return ("SSL - Invalid value in SSL config"); -#endif /* MBEDTLS_SSL_TLS_C */ - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) - case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): - return ( - "X509 - Unavailable feature, e.g. RSA hashing/encryption combination"); - case -(MBEDTLS_ERR_X509_UNKNOWN_OID): - return ("X509 - Requested OID is unknown"); - case -(MBEDTLS_ERR_X509_INVALID_FORMAT): - return ("X509 - The CRT/CRL/CSR format is invalid, e.g. different type " - "expected"); - case -(MBEDTLS_ERR_X509_INVALID_VERSION): - return ("X509 - The CRT/CRL/CSR version element is invalid"); - case -(MBEDTLS_ERR_X509_INVALID_SERIAL): - return ("X509 - The serial tag or value is invalid"); - case -(MBEDTLS_ERR_X509_INVALID_ALG): - return ("X509 - The algorithm tag or value is invalid"); - case -(MBEDTLS_ERR_X509_INVALID_NAME): - return ("X509 - The name tag or value is invalid"); - case -(MBEDTLS_ERR_X509_INVALID_DATE): - return ("X509 - The date tag or value is invalid"); - case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): - return ("X509 - The signature tag or value invalid"); - case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): - return ("X509 - The extension tag or value is invalid"); - case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): - return ("X509 - CRT/CRL/CSR has an unsupported version number"); - case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): - return ("X509 - Signature algorithm (oid) is unsupported"); - case -(MBEDTLS_ERR_X509_SIG_MISMATCH): - return ("X509 - Signature algorithms do not match. (see \\c " - "::mbedtls_x509_crt sig_oid)"); - case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): - return ("X509 - Certificate verification failed, e.g. CRL, CA or signature " - "check failed"); - case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): - return ("X509 - Format not recognized as DER or PEM"); - case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): - return ("X509 - Input invalid"); - case -(MBEDTLS_ERR_X509_ALLOC_FAILED): - return ("X509 - Allocation of memory failed"); - case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): - return ("X509 - Read/write of file failed"); - case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): - return ("X509 - Destination buffer is too small"); - case -(MBEDTLS_ERR_X509_FATAL_ERROR): - return ("X509 - A fatal error occurred, eg the chain is too long or the " - "vrfy callback failed"); -#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ - /* End Auto-Generated Code. */ - - default: - break; - } - - return (NULL); -} - -const char *mbedtls_low_level_strerr(int error_code) { - int low_level_error_code; - - if (error_code < 0) - error_code = -error_code; - - /* Extract the low-level part from the error code. */ - low_level_error_code = error_code & ~0xFF80; - - switch (low_level_error_code) { - /* Begin Auto-Generated Code. */ -#if defined(MBEDTLS_AES_C) - case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): - return ("AES - Invalid key length"); - case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): - return ("AES - Invalid data input length"); - case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): - return ("AES - Invalid input data"); - case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE): - return ("AES - Feature not available. For example, an unsupported AES key " - "size"); - case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED): - return ("AES - AES hardware accelerator failed"); -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ARC4_C) - case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED): - return ("ARC4 - ARC4 hardware accelerator failed"); -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_ARIA_C) - case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): - return ("ARIA - Bad input data"); - case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): - return ("ARIA - Invalid data input length"); - case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE): - return ("ARIA - Feature not available. For example, an unsupported ARIA " - "key size"); - case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED): - return ("ARIA - ARIA hardware accelerator failed"); -#endif /* MBEDTLS_ARIA_C */ - -#if defined(MBEDTLS_ASN1_PARSE_C) - case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): - return ("ASN1 - Out of data when parsing an ASN1 data structure"); - case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): - return ("ASN1 - ASN1 tag was of an unexpected value"); - case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): - return ( - "ASN1 - Error when trying to determine the length or invalid length"); - case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): - return ("ASN1 - Actual length differs from expected length"); - case -(MBEDTLS_ERR_ASN1_INVALID_DATA): - return ("ASN1 - Data is invalid"); - case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): - return ("ASN1 - Memory allocation failed"); - case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): - return ("ASN1 - Buffer too small when writing ASN.1 data structure"); -#endif /* MBEDTLS_ASN1_PARSE_C */ - -#if defined(MBEDTLS_BASE64_C) - case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): - return ("BASE64 - Output buffer too small"); - case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): - return ("BASE64 - Invalid character in input"); -#endif /* MBEDTLS_BASE64_C */ - -#if defined(MBEDTLS_BIGNUM_C) - case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): - return ( - "BIGNUM - An error occurred while reading from or writing to a file"); - case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): - return ("BIGNUM - Bad input parameters to function"); - case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): - return ("BIGNUM - There is an invalid character in the digit string"); - case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): - return ("BIGNUM - The buffer is too small to write to"); - case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): - return ("BIGNUM - The input arguments are negative or result in illegal " - "output"); - case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): - return ("BIGNUM - The input argument for division is zero, which is not " - "allowed"); - case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): - return ("BIGNUM - The input arguments are not acceptable"); - case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): - return ("BIGNUM - Memory allocation failed"); -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_BLOWFISH_C) - case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA): - return ("BLOWFISH - Bad input data"); - case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH): - return ("BLOWFISH - Invalid data input length"); - case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED): - return ("BLOWFISH - Blowfish hardware accelerator failed"); -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): - return ("CAMELLIA - Bad input data"); - case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): - return ("CAMELLIA - Invalid data input length"); - case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED): - return ("CAMELLIA - Camellia hardware accelerator failed"); -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_CCM_C) - case -(MBEDTLS_ERR_CCM_BAD_INPUT): - return ("CCM - Bad input parameters to the function"); - case -(MBEDTLS_ERR_CCM_AUTH_FAILED): - return ("CCM - Authenticated decryption failed"); - case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED): - return ("CCM - CCM hardware accelerator failed"); -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_CHACHA20_C) - case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): - return ("CHACHA20 - Invalid input parameter(s)"); - case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE): - return ("CHACHA20 - Feature not available. For example, s part of the API " - "is not implemented"); - case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED): - return ("CHACHA20 - Chacha20 hardware accelerator failed"); -#endif /* MBEDTLS_CHACHA20_C */ - -#if defined(MBEDTLS_CHACHAPOLY_C) - case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): - return ("CHACHAPOLY - The requested operation is not permitted in the " - "current state"); - case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): - return ( - "CHACHAPOLY - Authenticated decryption failed: data was not authentic"); -#endif /* MBEDTLS_CHACHAPOLY_C */ - -#if defined(MBEDTLS_CMAC_C) - case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED): - return ("CMAC - CMAC hardware accelerator failed"); -#endif /* MBEDTLS_CMAC_C */ - -#if defined(MBEDTLS_CTR_DRBG_C) - case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): - return ("CTR_DRBG - The entropy source failed"); - case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): - return ("CTR_DRBG - The requested random buffer length is too big"); - case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): - return ("CTR_DRBG - The input (entropy + additional data) is too large"); - case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): - return ("CTR_DRBG - Read or write error in file"); -#endif /* MBEDTLS_CTR_DRBG_C */ - -#if defined(MBEDTLS_DES_C) - case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): - return ("DES - The data input has an invalid length"); - case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED): - return ("DES - DES hardware accelerator failed"); -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ENTROPY_C) - case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): - return ("ENTROPY - Critical entropy source failure"); - case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): - return ("ENTROPY - No more sources can be added"); - case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): - return ("ENTROPY - No sources have been added to poll"); - case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): - return ("ENTROPY - No strong sources have been added to poll"); - case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): - return ("ENTROPY - Read/write error in file"); -#endif /* MBEDTLS_ENTROPY_C */ - -#if defined(MBEDTLS_ERROR_C) - case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): - return ("ERROR - Generic error"); - case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): - return ("ERROR - This is a bug in the library"); -#endif /* MBEDTLS_ERROR_C */ - -#if defined(MBEDTLS_GCM_C) - case -(MBEDTLS_ERR_GCM_AUTH_FAILED): - return ("GCM - Authenticated decryption failed"); - case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED): - return ("GCM - GCM hardware accelerator failed"); - case -(MBEDTLS_ERR_GCM_BAD_INPUT): - return ("GCM - Bad input parameters to function"); -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_HKDF_C) - case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): - return ("HKDF - Bad input parameters to function"); -#endif /* MBEDTLS_HKDF_C */ - -#if defined(MBEDTLS_HMAC_DRBG_C) - case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): - return ("HMAC_DRBG - Too many random requested in single call"); - case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): - return ("HMAC_DRBG - Input too large (Entropy + additional)"); - case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): - return ("HMAC_DRBG - Read/write error in file"); - case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): - return ("HMAC_DRBG - The entropy source failed"); -#endif /* MBEDTLS_HMAC_DRBG_C */ - -#if defined(MBEDTLS_MD2_C) - case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED): - return ("MD2 - MD2 hardware accelerator failed"); -#endif /* MBEDTLS_MD2_C */ - -#if defined(MBEDTLS_MD4_C) - case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED): - return ("MD4 - MD4 hardware accelerator failed"); -#endif /* MBEDTLS_MD4_C */ - -#if defined(MBEDTLS_MD5_C) - case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED): - return ("MD5 - MD5 hardware accelerator failed"); -#endif /* MBEDTLS_MD5_C */ - -#if defined(MBEDTLS_NET_C) - case -(MBEDTLS_ERR_NET_SOCKET_FAILED): - return ("NET - Failed to open a socket"); - case -(MBEDTLS_ERR_NET_CONNECT_FAILED): - return ("NET - The connection to the given server / port failed"); - case -(MBEDTLS_ERR_NET_BIND_FAILED): - return ("NET - Binding of the socket failed"); - case -(MBEDTLS_ERR_NET_LISTEN_FAILED): - return ("NET - Could not listen on the socket"); - case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): - return ("NET - Could not accept the incoming connection"); - case -(MBEDTLS_ERR_NET_RECV_FAILED): - return ("NET - Reading information from the socket failed"); - case -(MBEDTLS_ERR_NET_SEND_FAILED): - return ("NET - Sending information through the socket failed"); - case -(MBEDTLS_ERR_NET_CONN_RESET): - return ("NET - Connection was reset by peer"); - case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): - return ("NET - Failed to get an IP address for the given hostname"); - case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): - return ("NET - Buffer is too small to hold the data"); - case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): - return ("NET - The context is invalid, eg because it was free()ed"); - case -(MBEDTLS_ERR_NET_POLL_FAILED): - return ("NET - Polling the net context failed"); - case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): - return ("NET - Input invalid"); -#endif /* MBEDTLS_NET_C */ - -#if defined(MBEDTLS_OID_C) - case -(MBEDTLS_ERR_OID_NOT_FOUND): - return ("OID - OID is not found"); - case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): - return ("OID - output buffer is too small"); -#endif /* MBEDTLS_OID_C */ - -#if defined(MBEDTLS_PADLOCK_C) - case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED): - return ("PADLOCK - Input data should be aligned"); -#endif /* MBEDTLS_PADLOCK_C */ - -#if defined(MBEDTLS_PLATFORM_C) - case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): - return ("PLATFORM - Hardware accelerator failed"); - case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): - return ( - "PLATFORM - The requested feature is not supported by the platform"); -#endif /* MBEDTLS_PLATFORM_C */ - -#if defined(MBEDTLS_POLY1305_C) - case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): - return ("POLY1305 - Invalid input parameter(s)"); - case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE): - return ("POLY1305 - Feature not available. For example, s part of the API " - "is not implemented"); - case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED): - return ("POLY1305 - Poly1305 hardware accelerator failed"); -#endif /* MBEDTLS_POLY1305_C */ - -#if defined(MBEDTLS_RIPEMD160_C) - case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED): - return ("RIPEMD160 - RIPEMD160 hardware accelerator failed"); -#endif /* MBEDTLS_RIPEMD160_C */ - -#if defined(MBEDTLS_SHA1_C) - case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED): - return ("SHA1 - SHA-1 hardware accelerator failed"); - case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): - return ("SHA1 - SHA-1 input data was malformed"); -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED): - return ("SHA256 - SHA-256 hardware accelerator failed"); - case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): - return ("SHA256 - SHA-256 input data was malformed"); -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED): - return ("SHA512 - SHA-512 hardware accelerator failed"); - case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): - return ("SHA512 - SHA-512 input data was malformed"); -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_THREADING_C) - case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE): - return ("THREADING - The selected feature is not available"); - case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): - return ("THREADING - Bad input parameters to function"); - case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): - return ("THREADING - Locking / unlocking / free failed with error code"); -#endif /* MBEDTLS_THREADING_C */ - -#if defined(MBEDTLS_XTEA_C) - case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH): - return ("XTEA - The data input has an invalid length"); - case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED): - return ("XTEA - XTEA hardware accelerator failed"); -#endif /* MBEDTLS_XTEA_C */ - -#if defined(TINYCRYPT_PRIMITIVES) - case UECC_FAILURE: - return ("TinyCrypt - uECC failure"); - case UECC_FAULT_DETECTED: - return ("TinyCrypt - uECC fault detected"); -#endif /* TINYCRYPT_PRIMITIVES */ - /* End Auto-Generated Code. */ - - default: - break; - } - - return (NULL); -} - -void mbedtls_strerror(int ret, char *buf, size_t buflen) { - size_t len; - int use_ret; - const char *high_level_error_description = NULL; - const char *low_level_error_description = NULL; - - if (buflen == 0) - return; - - memset(buf, 0x00, buflen); - - if (ret < 0) - ret = -ret; - - if (ret & 0xFF80) { - use_ret = ret & 0xFF80; - - // Translate high level error code. - high_level_error_description = mbedtls_high_level_strerr(ret); - - if (high_level_error_description == NULL) - mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", - (unsigned int)use_ret); - else - mbedtls_snprintf(buf, buflen, "%s", high_level_error_description); - -#if defined(MBEDTLS_SSL_TLS_C) - // Early return in case of a fatal error - do not try to translate low - // level code. - if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) - return; -#endif /* MBEDTLS_SSL_TLS_C */ - } - - use_ret = ret & ~0xFF80; - - if (use_ret == 0) - return; - - // If high level code is present, make a concatenation between both - // error strings. - // - len = strlen(buf); - - if (len > 0) { - if (buflen - len < 5) - return; - - mbedtls_snprintf(buf + len, buflen - len, " : "); - - buf += len + 3; - buflen -= len + 3; - } - - // Translate low level error code. - low_level_error_description = mbedtls_low_level_strerr(ret); - - if (low_level_error_description == NULL) - mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", - (unsigned int)use_ret); - else - mbedtls_snprintf(buf, buflen, "%s", low_level_error_description); -} - -#else /* MBEDTLS_ERROR_C */ - -/* - * Provide an non-function in case MBEDTLS_ERROR_C is not defined - */ -void mbedtls_strerror(int ret, char *buf, size_t buflen) { - ((void)ret); - - if (buflen > 0) - buf[0] = '\0'; -} - -#endif /* MBEDTLS_ERROR_C */ - -#if defined(MBEDTLS_TEST_HOOKS) -void (*mbedtls_test_hook_error_add)(int, int, const char *, int); -#endif - -#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/matter/mbedtls/tinycrypt/src/hmac.c b/matter/mbedtls/tinycrypt/src/hmac.c deleted file mode 100644 index 89878cec78..0000000000 --- a/matter/mbedtls/tinycrypt/src/hmac.c +++ /dev/null @@ -1,148 +0,0 @@ -/* hmac.c - TinyCrypt implementation of the HMAC algorithm */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) -{ - const uint8_t inner_pad = (uint8_t) 0x36; - const uint8_t outer_pad = (uint8_t) 0x5c; - unsigned int i; - - for (i = 0; i < key_size; ++i) { - key[i] = inner_pad ^ new_key[i]; - key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i]; - } - for (; i < TC_SHA256_BLOCK_SIZE; ++i) { - key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad; - } -} - -int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key, - unsigned int key_size) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0 || - key == (const uint8_t *) 0 || - key_size == 0) { - return TC_CRYPTO_FAIL; - } - - const uint8_t dummy_key[key_size]; - struct tc_hmac_state_struct dummy_state; - - if (key_size <= TC_SHA256_BLOCK_SIZE) { - /* - * The next three lines consist of dummy calls just to avoid - * certain timing attacks. Without these dummy calls, - * adversaries would be able to learn whether the key_size is - * greater than TC_SHA256_BLOCK_SIZE by measuring the time - * consumed in this process. - */ - (void)tc_sha256_init(&dummy_state.hash_state); - (void)tc_sha256_update(&dummy_state.hash_state, - dummy_key, - key_size); - (void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE], - &dummy_state.hash_state); - - /* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */ - rekey(ctx->key, key, key_size); - } else { - (void)tc_sha256_init(&ctx->hash_state); - (void)tc_sha256_update(&ctx->hash_state, key, key_size); - (void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE], - &ctx->hash_state); - rekey(ctx->key, - &ctx->key[TC_SHA256_DIGEST_SIZE], - TC_SHA256_DIGEST_SIZE); - } - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_init(TCHmacState_t ctx) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void) tc_sha256_init(&ctx->hash_state); - (void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE); - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_update(TCHmacState_t ctx, - const void *data, - unsigned int data_length) -{ - - /* input sanity check: */ - if (ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void)tc_sha256_update(&ctx->hash_state, data, data_length); - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx) -{ - - /* input sanity check: */ - if (tag == (uint8_t *) 0 || - taglen != TC_SHA256_DIGEST_SIZE || - ctx == (TCHmacState_t) 0) { - return TC_CRYPTO_FAIL; - } - - (void) tc_sha256_final(tag, &ctx->hash_state); - - (void)tc_sha256_init(&ctx->hash_state); - (void)tc_sha256_update(&ctx->hash_state, - &ctx->key[TC_SHA256_BLOCK_SIZE], - TC_SHA256_BLOCK_SIZE); - (void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE); - (void)tc_sha256_final(tag, &ctx->hash_state); - - /* destroy the current state */ - _set(ctx, 0, sizeof(*ctx)); - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/hmac_prng.c b/matter/mbedtls/tinycrypt/src/hmac_prng.c deleted file mode 100644 index 68b5b1fafb..0000000000 --- a/matter/mbedtls/tinycrypt/src/hmac_prng.c +++ /dev/null @@ -1,212 +0,0 @@ -/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -/* - * min bytes in the seed string. - * MIN_SLEN*8 must be at least the expected security level. - */ -static const unsigned int MIN_SLEN = 32; - -/* - * max bytes in the seed string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_SLEN = UINT32_MAX; - -/* - * max bytes in the personalization string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_PLEN = UINT32_MAX; - -/* - * max bytes in the additional_info string; - * SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes). - */ -static const unsigned int MAX_ALEN = UINT32_MAX; - -/* - * max number of generates between re-seeds; - * TinyCrypt accepts up to (2^32 - 1) which is the maximal value of - * a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48. - */ -static const unsigned int MAX_GENS = UINT32_MAX; - -/* - * maximum bytes per generate call; - * SP800-90A specifies a maximum up to 2^19. - */ -static const unsigned int MAX_OUT = (1 << 19); - -/* - * Assumes: prng != NULL, e != NULL, len >= 0. - */ -static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len) -{ - const uint8_t separator0 = 0x00; - const uint8_t separator1 = 0x01; - - /* use current state, e and separator 0 to compute a new prng key: */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0)); - (void)tc_hmac_update(&prng->h, e, len); - (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ - (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - - /* use the new key to compute a new state variable v */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); - - /* use current state, e and separator 1 to compute a new prng key: */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1)); - (void)tc_hmac_update(&prng->h, e, len); - (void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h); - /* configure the new prng key into the prng's instance of hmac */ - (void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - - /* use the new key to compute a new state variable v */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); -} - -int tc_hmac_prng_init(TCHmacPrng_t prng, - const uint8_t *personalization, - unsigned int plen) -{ - - /* input sanity check: */ - if (prng == (TCHmacPrng_t) 0 || - personalization == (uint8_t *) 0 || - plen > MAX_PLEN) { - return TC_CRYPTO_FAIL; - } - - /* put the generator into a known state: */ - _set(prng->key, 0x00, sizeof(prng->key)); - _set(prng->v, 0x01, sizeof(prng->v)); - tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key)); - /* update assumes SOME key has been configured into HMAC */ - - update(prng, personalization, plen); - - /* force a reseed before allowing tc_hmac_prng_generate to succeed: */ - prng->countdown = 0; - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_prng_reseed(TCHmacPrng_t prng, - const uint8_t *seed, - unsigned int seedlen, - const uint8_t *additional_input, - unsigned int additionallen) -{ - - /* input sanity check: */ - if (prng == (TCHmacPrng_t) 0 || - seed == (const uint8_t *) 0 || - seedlen < MIN_SLEN || - seedlen > MAX_SLEN) { - return TC_CRYPTO_FAIL; - } - - if (additional_input != (const uint8_t *) 0) { - /* - * Abort if additional_input is provided but has inappropriate - * length - */ - if (additionallen == 0 || - additionallen > MAX_ALEN) { - return TC_CRYPTO_FAIL; - } else { - /* call update for the seed and additional_input */ - update(prng, seed, seedlen); - update(prng, additional_input, additionallen); - } - } else { - /* call update only for the seed */ - update(prng, seed, seedlen); - } - - /* ... and enable hmac_prng_generate */ - prng->countdown = MAX_GENS; - - return TC_CRYPTO_SUCCESS; -} - -int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng) -{ - unsigned int bufferlen; - - /* input sanity check: */ - if (out == (uint8_t *) 0 || - prng == (TCHmacPrng_t) 0 || - outlen == 0 || - outlen > MAX_OUT) { - return TC_CRYPTO_FAIL; - } else if (prng->countdown == 0) { - return TC_HMAC_PRNG_RESEED_REQ; - } - - prng->countdown--; - - while (outlen != 0) { - /* operate HMAC in OFB mode to create "random" outputs */ - (void)tc_hmac_init(&prng->h); - (void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v)); - (void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h); - - bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ? - outlen : TC_SHA256_DIGEST_SIZE; - (void)_copy(out, bufferlen, prng->v, bufferlen); - - out += bufferlen; - outlen = (outlen > TC_SHA256_DIGEST_SIZE) ? - (outlen - TC_SHA256_DIGEST_SIZE) : 0; - } - - /* block future PRNG compromises from revealing past state */ - update(prng, prng->v, TC_SHA256_DIGEST_SIZE); - - return TC_CRYPTO_SUCCESS; -} diff --git a/matter/mbedtls/tinycrypt/src/oid.c b/matter/mbedtls/tinycrypt/src/oid.c new file mode 100644 index 0000000000..d139a6d0de --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/oid.c @@ -0,0 +1,1166 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * 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. + */ + +#include "common.h" + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" +#include "mbedtls/pk.h" + +#include +#include + +#include "mbedtls/platform.h" + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate mbedtls_oid_descriptor_t + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } +#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } +#else +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } +#define NULL_OID_DESCRIPTOR { NULL, 0 } +#endif + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST) \ + static const TYPE_T *oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if (p == NULL || oid == NULL) return NULL; \ + while (cur->asn1 != NULL) { \ + if (cur->asn1_len == oid->len && \ + memcmp(cur->asn1, oid->p, oid->len) == 0) { \ + return p; \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return NULL; \ + } + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ + int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ + { \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ + if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ + *ATTR1 = data->descriptor.ATTR1; \ + return 0; \ + } +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ + int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ + { \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ + if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ + *ATTR1 = data->ATTR1; \ + return 0; \ + } + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ + int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2) \ + { \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ + if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return 0; \ + } + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ + int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen) \ + { \ + const TYPE_T *cur = (LIST); \ + while (cur->descriptor.asn1 != NULL) { \ + if (cur->ATTR1 == (ATTR1)) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return 0; \ + } \ + cur++; \ + } \ + return MBEDTLS_ERR_OID_NOT_FOUND; \ + } + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ + int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid, \ + size_t *olen) \ + { \ + const TYPE_T *cur = (LIST); \ + while (cur->descriptor.asn1 != NULL) { \ + if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return 0; \ + } \ + cur++; \ + } \ + return MBEDTLS_ERR_OID_NOT_FOUND; \ + } + +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), + "CN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), + "C", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), + "L", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), + "ST", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", + "Organization"), + "O", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), + "OU", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, + "emailAddress", + "E-mail address"), + "emailAddress", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, + "id-at-serialNumber", + "Serial number"), + "serialNumber", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, + "id-at-postalAddress", + "Postal address"), + "postalAddress", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), + "postalCode", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), + "SN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), + "GN", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), + "initials", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, + "id-at-generationQualifier", + "Generation qualifier"), + "generationQualifier", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), + "title", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, + "id-at-dnQualifier", + "Distinguished Name qualifier"), + "dnQualifier", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), + "pseudonym", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), + "uid", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, + "id-domainComponent", + "Domain component"), + "DC", + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, + "id-at-uniqueIdentifier", + "Unique Identifier"), + "uniqueIdentifier", + }, + { + NULL_OID_DESCRIPTOR, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, + oid_x520_attr_t, + x520_attr, + const char *, + short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, + "id-ce-basicConstraints", + "Basic Constraints"), + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, + "id-ce-extKeyUsage", + "Extended Key Usage"), + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, + "id-ce-subjectAltName", + "Subject Alt Name"), + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, + "id-netscape-certtype", + "Netscape Certificate Type"), + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, + "id-ce-certificatePolicies", + "Certificate Policies"), + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + "id-ce-subjectKeyIdentifier", + "Subject Key Identifier"), + MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + "id-ce-authorityKeyIdentifier", + "Authority Key Identifier"), + MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, + }, + { + NULL_OID_DESCRIPTOR, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, + "id-kp-serverAuth", + "TLS Web Server Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, + "id-kp-clientAuth", + "TLS Web Client Authentication"), + OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), + OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), + OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), + OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, + "id-kp-wisun-fan-device", + "Wi-SUN Alliance Field Area Network (FAN)"), + NULL_OID_DESCRIPTOR, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, + mbedtls_oid_descriptor_t, + ext_key_usage, + const char *, + description) + +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), + NULL_OID_DESCRIPTOR, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, + mbedtls_oid_descriptor_t, + certificate_policies, + const char *, + description) +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD_CAN_MD5) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_MD5 */ +#if defined(MBEDTLS_MD_CAN_SHA1) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", + "RSA with SHA-224"), + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA224 */ +#if defined(MBEDTLS_MD_CAN_SHA256) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", + "RSA with SHA-256"), + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", + "RSA with SHA-384"), + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", + "RSA with SHA-512"), + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#if defined(MBEDTLS_MD_CAN_SHA1) + { + OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#if defined(MBEDTLS_MD_CAN_SHA1) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) + { + OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ +#if defined(MBEDTLS_RSA_C) + { + OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, + oid_sig_alg_t, + sig_alg, + const char *, + description) +#endif + +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, + oid_sig_alg_t, + sig_alg, + mbedtls_md_type_t, + md_alg, + mbedtls_pk_type_t, + pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, + oid_sig_alg_t, + oid_sig_alg, + mbedtls_pk_type_t, + pk_alg, + mbedtls_md_type_t, + md_alg) + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), + MBEDTLS_PK_RSA, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), + MBEDTLS_PK_ECKEY, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), + MBEDTLS_PK_ECKEY_DH, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, + oid_pk_alg_t, + oid_pk_alg, + mbedtls_pk_type_t, + pk_alg) + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/* + * For elliptic curves that use namedCurve inside ECParams (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_HAVE_SECP192R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP192R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP224R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP224R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP256R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP256R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP384R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP384R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP521R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP521R1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP192K1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP192K1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP224K1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP224K1 */ +#if defined(MBEDTLS_ECP_HAVE_SECP256K1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_HAVE_SECP256K1 */ +#if defined(MBEDTLS_ECP_HAVE_BP256R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_HAVE_BP256R1 */ +#if defined(MBEDTLS_ECP_HAVE_BP384R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_HAVE_BP384R1 */ +#if defined(MBEDTLS_ECP_HAVE_BP512R1) + { + OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_HAVE_BP512R1 */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, + oid_ecp_grp_t, + oid_ecp_grp, + mbedtls_ecp_group_id, + grp_id) + +/* + * For Elliptic Curve algorithms that are directly + * encoded in the AlgorithmIdentifier (RFC 8410) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_algid_t; + +static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] = +{ +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + { + OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"), + MBEDTLS_ECP_DP_CURVE25519, + }, +#endif /* MBEDTLS_ECP_HAVE_CURVE25519 */ +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + { + OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"), + MBEDTLS_ECP_DP_CURVE448, + }, +#endif /* MBEDTLS_ECP_HAVE_CURVE448 */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid, + oid_ecp_grp_algid_t, + grp_id_algid, + mbedtls_ecp_group_id, + grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid, + oid_ecp_grp_algid_t, + oid_ecp_grp_algid, + mbedtls_ecp_group_id, + grp_id) +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), + MBEDTLS_CIPHER_DES_CBC, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, + oid_cipher_alg_t, + cipher_alg, + mbedtls_cipher_type_t, + cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD_CAN_MD5) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), + MBEDTLS_MD_MD5, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA1) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), + MBEDTLS_MD_SHA1, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA224) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA256) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), + MBEDTLS_MD_SHA256, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA384) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), + MBEDTLS_MD_SHA384, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA512) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), + MBEDTLS_MD_SHA512, + }, +#endif +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), + MBEDTLS_MD_RIPEMD160, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_224) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224, "id-sha3-224", "SHA-3-224"), + MBEDTLS_MD_SHA3_224, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_256) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256, "id-sha3-256", "SHA-3-256"), + MBEDTLS_MD_SHA3_256, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_384) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384, "id-sha3-384", "SHA-3-384"), + MBEDTLS_MD_SHA3_384, + }, +#endif +#if defined(MBEDTLS_MD_CAN_SHA3_512) + { + OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512, "id-sha3-512", "SHA-3-512"), + MBEDTLS_MD_SHA3_512, + }, +#endif + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, + oid_md_alg_t, + oid_md_alg, + mbedtls_md_type_t, + md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_MD_CAN_SHA1) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_MD_CAN_SHA1 */ +#if defined(MBEDTLS_MD_CAN_SHA224) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), + MBEDTLS_MD_SHA224, + }, +#endif /* MBEDTLS_MD_CAN_SHA224 */ +#if defined(MBEDTLS_MD_CAN_SHA256) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_MD_CAN_SHA256 */ +#if defined(MBEDTLS_MD_CAN_SHA384) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_MD_CAN_SHA384 */ +#if defined(MBEDTLS_MD_CAN_SHA512) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_MD_CAN_SHA512 */ +#if defined(MBEDTLS_MD_CAN_SHA3_224) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224, "hmacSHA3-224", "HMAC-SHA3-224"), + MBEDTLS_MD_SHA3_224, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_224 */ +#if defined(MBEDTLS_MD_CAN_SHA3_256) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256, "hmacSHA3-256", "HMAC-SHA3-256"), + MBEDTLS_MD_SHA3_256, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_256 */ +#if defined(MBEDTLS_MD_CAN_SHA3_384) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384, "hmacSHA3-384", "HMAC-SHA3-384"), + MBEDTLS_MD_SHA3_384, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_384 */ +#if defined(MBEDTLS_MD_CAN_SHA3_512) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512, "hmacSHA3-512", "HMAC-SHA3-512"), + MBEDTLS_MD_SHA3_512, + }, +#endif /* MBEDTLS_MD_CAN_SHA3_512 */ +#if defined(MBEDTLS_MD_CAN_RIPEMD160) + { + OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160, "hmacRIPEMD160", "HMAC-RIPEMD160"), + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_MD_CAN_RIPEMD160 */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, + "pbeWithSHAAnd3-KeyTripleDES-CBC", + "PBE with SHA1 and 3-Key 3DES"), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, + "pbeWithSHAAnd2-KeyTripleDES-CBC", + "PBE with SHA1 and 2-Key 3DES"), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, + oid_pkcs12_pbe_alg_t, + pkcs12_pbe_alg, + mbedtls_md_type_t, + md_alg, + mbedtls_cipher_type_t, + cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string(char *buf, size_t size, + const mbedtls_asn1_buf *oid) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + char *p = buf; + size_t n = size; + unsigned int value = 0; + + if (size > INT_MAX) { + /* Avoid overflow computing return value */ + return MBEDTLS_ERR_ASN1_INVALID_LENGTH; + } + + if (oid->len <= 0) { + /* OID must not be empty */ + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + + for (size_t i = 0; i < oid->len; i++) { + /* Prevent overflow in value. */ + if (value > (UINT_MAX >> 7)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + if ((value == 0) && ((oid->p[i]) == 0x80)) { + /* Overlong encoding is not allowed */ + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + + value <<= 7; + value |= oid->p[i] & 0x7F; + + if (!(oid->p[i] & 0x80)) { + /* Last byte */ + if (n == size) { + int component1; + unsigned int component2; + /* First subidentifier contains first two OID components */ + if (value >= 80) { + component1 = '2'; + component2 = value - 80; + } else if (value >= 40) { + component1 = '1'; + component2 = value - 40; + } else { + component1 = '0'; + component2 = value; + } + ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); + } else { + ret = mbedtls_snprintf(p, n, ".%u", value); + } + if (ret < 2 || (size_t) ret >= n) { + return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + } + n -= (size_t) ret; + p += ret; + value = 0; + } + } + + if (value != 0) { + /* Unterminated subidentifier */ + return MBEDTLS_ERR_ASN1_OUT_OF_DATA; + } + + return (int) (size - n); +} + +static int oid_parse_number(unsigned int *num, const char **p, const char *bound) +{ + int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + + *num = 0; + + while (*p < bound && **p >= '0' && **p <= '9') { + ret = 0; + if (*num > (UINT_MAX / 10)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + *num *= 10; + *num += **p - '0'; + (*p)++; + } + return ret; +} + +static size_t oid_subidentifier_num_bytes(unsigned int value) +{ + size_t num_bytes = 0; + + do { + value >>= 7; + num_bytes++; + } while (value != 0); + + return num_bytes; +} + +static int oid_subidentifier_encode_into(unsigned char **p, + unsigned char *bound, + unsigned int value) +{ + size_t num_bytes = oid_subidentifier_num_bytes(value); + + if ((size_t) (bound - *p) < num_bytes) { + return MBEDTLS_ERR_OID_BUF_TOO_SMALL; + } + (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f); + value >>= 7; + + for (size_t i = 2; i <= num_bytes; i++) { + (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f); + value >>= 7; + } + *p += num_bytes; + + return 0; +} + +/* Return the OID for the given x.y.z.... style numeric string */ +int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, + const char *oid_str, size_t size) +{ + int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + const char *str_ptr = oid_str; + const char *str_bound = oid_str + size; + unsigned int val = 0; + unsigned int component1, component2; + size_t encoded_len; + unsigned char *resized_mem; + + /* Count the number of dots to get a worst-case allocation size. */ + size_t num_dots = 0; + for (size_t i = 0; i < size; i++) { + if (oid_str[i] == '.') { + num_dots++; + } + } + /* Allocate maximum possible required memory: + * There are (num_dots + 1) integer components, but the first 2 share the + * same subidentifier, so we only need num_dots subidentifiers maximum. */ + if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) { + return MBEDTLS_ERR_ASN1_INVALID_DATA; + } + /* Each byte can store 7 bits, calculate number of bytes for a + * subidentifier: + * + * bytes = ceil(subidentifer_size * 8 / 7) + */ + size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7) + + 1; + size_t max_possible_bytes = num_dots * bytes_per_subidentifier; + oid->p = mbedtls_calloc(max_possible_bytes, 1); + if (oid->p == NULL) { + return MBEDTLS_ERR_ASN1_ALLOC_FAILED; + } + unsigned char *out_ptr = oid->p; + unsigned char *out_bound = oid->p + max_possible_bytes; + + ret = oid_parse_number(&component1, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if (component1 > 2) { + /* First component can't be > 2 */ + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + if (str_ptr >= str_bound || *str_ptr != '.') { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + str_ptr++; + + ret = oid_parse_number(&component2, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if ((component1 < 2) && (component2 > 39)) { + /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */ + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + if (str_ptr < str_bound) { + if (*str_ptr == '.') { + str_ptr++; + } else { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + } + + if (component2 > (UINT_MAX - (component1 * 40))) { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + ret = oid_subidentifier_encode_into(&out_ptr, out_bound, + (component1 * 40) + component2); + if (ret != 0) { + goto error; + } + + while (str_ptr < str_bound) { + ret = oid_parse_number(&val, &str_ptr, str_bound); + if (ret != 0) { + goto error; + } + if (str_ptr < str_bound) { + if (*str_ptr == '.') { + str_ptr++; + } else { + ret = MBEDTLS_ERR_ASN1_INVALID_DATA; + goto error; + } + } + + ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val); + if (ret != 0) { + goto error; + } + } + + encoded_len = out_ptr - oid->p; + resized_mem = mbedtls_calloc(encoded_len, 1); + if (resized_mem == NULL) { + ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; + goto error; + } + memcpy(resized_mem, oid->p, encoded_len); + mbedtls_free(oid->p); + oid->p = resized_mem; + oid->len = encoded_len; + + oid->tag = MBEDTLS_ASN1_OID; + + return 0; + +error: + mbedtls_free(oid->p); + oid->p = NULL; + oid->len = 0; + return ret; +} + +#endif /* MBEDTLS_OID_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk.c b/matter/mbedtls/tinycrypt/src/pk.c new file mode 100644 index 0000000000..96b8ef9220 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/pk.c @@ -0,0 +1,982 @@ +/* + * Public Key abstraction layer + * + * 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. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "pk_wrap.h" +#include "pkwrite.h" +#include "pk_internal.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa_util_internal.h" +#include "md_psa.h" +#endif + +#include +#include + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init(mbedtls_pk_context *ctx) +{ + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +#if defined(MBEDTLS_PSA_CRYPTO_C) + ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT; +#endif /* MBEDTLS_PSA_CRYPTO_C */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw)); + ctx->pub_raw_len = 0; + ctx->ec_family = 0; + ctx->ec_bits = 0; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free(mbedtls_pk_context *ctx) +{ + if (ctx == NULL) { + return; + } + + if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { + ctx->pk_info->ctx_free_func(ctx->pk_ctx); + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + /* The ownership of the priv_id key for opaque keys is external of the PK + * module. It's the user responsibility to clear it after use. */ + if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) { + psa_destroy_key(ctx->priv_id); + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) +{ + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx) +{ + if (ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL) { + return; + } + + ctx->pk_info->rs_free_func(ctx->rs_ctx); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) +{ + switch (pk_type) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return &mbedtls_rsa_info; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + case MBEDTLS_PK_ECKEY: + return &mbedtls_eckey_info; + case MBEDTLS_PK_ECKEY_DH: + return &mbedtls_eckeydh_info; +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) + case MBEDTLS_PK_ECDSA: + return &mbedtls_ecdsa_info; +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return NULL; + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) +{ + if (info == NULL || ctx->pk_info != NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if ((info->ctx_alloc_func != NULL) && + ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + ctx->pk_info = info; + + return 0; +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Initialise a PSA-wrapping context + */ +int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, + const mbedtls_svc_key_id_t key) +{ + const mbedtls_pk_info_t *info = NULL; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t type; + + if (ctx == NULL || ctx->pk_info != NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + type = psa_get_key_type(&attributes); + psa_reset_key_attributes(&attributes); + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { + info = &mbedtls_ecdsa_opaque_info; + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { + info = &mbedtls_rsa_opaque_info; + } else { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + + ctx->pk_info = info; + ctx->priv_id = key; + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + if (ctx->pk_info != NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return 0; +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if (ctx == NULL || ctx->pk_info == NULL) { + return 0; + } + + return ctx->pk_info->can_do(type); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Tell if a PK can do the operations of the given PSA algorithm + */ +int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, + psa_key_usage_t usage) +{ + psa_key_usage_t key_usage; + + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if (ctx == NULL || ctx->pk_info == NULL) { + return 0; + } + + /* Filter out non allowed algorithms */ + if (PSA_ALG_IS_ECDSA(alg) == 0 && + PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && + PSA_ALG_IS_RSA_PSS(alg) == 0 && + alg != PSA_ALG_RSA_PKCS1V15_CRYPT && + PSA_ALG_IS_ECDH(alg) == 0) { + return 0; + } + + /* Filter out non allowed usage flags */ + if (usage == 0 || + (usage & ~(PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_DERIVE)) != 0) { + return 0; + } + + /* Wildcard hash is not allowed */ + if (PSA_ALG_IS_SIGN_HASH(alg) && + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { + return 0; + } + + if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { + mbedtls_pk_type_t type; + + if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { + type = MBEDTLS_PK_ECKEY; + } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || + alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { + type = MBEDTLS_PK_RSA; + } else if (PSA_ALG_IS_RSA_PSS(alg)) { + type = MBEDTLS_PK_RSASSA_PSS; + } else { + return 0; + } + + if (ctx->pk_info->can_do(type) == 0) { + return 0; + } + + switch (type) { + case MBEDTLS_PK_ECKEY: + key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; + break; + case MBEDTLS_PK_RSA: + case MBEDTLS_PK_RSASSA_PSS: + key_usage = PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_DECRYPT; + break; + default: + /* Should never happen */ + return 0; + } + + return (key_usage & usage) == usage; + } + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t key_alg, key_alg2; + psa_status_t status; + + status = psa_get_key_attributes(ctx->priv_id, &attributes); + if (status != PSA_SUCCESS) { + return 0; + } + + key_alg = psa_get_key_algorithm(&attributes); + key_alg2 = psa_get_key_enrollment_algorithm(&attributes); + key_usage = psa_get_key_usage_flags(&attributes); + psa_reset_key_attributes(&attributes); + + if ((key_usage & usage) != usage) { + return 0; + } + + /* + * Common case: the key alg or alg2 only allows alg. + * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH + * directly. + * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with + * a fixed hash on key_alg/key_alg2. + */ + if (alg == key_alg || alg == key_alg2) { + return 1; + } + + /* + * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash, + * and alg is the same hash-and-sign family with any hash, + * then alg is compliant with this key alg + */ + if (PSA_ALG_IS_SIGN_HASH(alg)) { + + if (PSA_ALG_IS_SIGN_HASH(key_alg) && + PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { + return 1; + } + + if (PSA_ALG_IS_SIGN_HASH(key_alg2) && + PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && + (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { + return 1; + } + } + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) +{ + if (*hash_len != 0) { + return 0; + } + + *hash_len = mbedtls_md_get_size_from_type(md_alg); + + if (*hash_len == 0) { + return -1; + } + + return 0; +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info) +{ + /* Don't do anything if already set up or invalid */ + if (ctx == NULL || ctx->pk_info != NULL) { + return 0; + } + + /* Should never happen when we're called */ + if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + ctx->pk_info = info; + + return 0; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info == NULL || + pk_hashlen_helper(md_alg, &hash_len) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if (rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { + return ret; + } + + ret = ctx->pk_info->verify_rs_func(ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); + + if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { + mbedtls_pk_restart_free(rs_ctx); + } + + return ret; + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if (ctx->pk_info->verify_func == NULL) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len, + sig, sig_len); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len, + sig, sig_len, NULL); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (!mbedtls_pk_can_do(ctx, type)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + if (type != MBEDTLS_PK_RSASSA_PSS) { + /* General case: no options */ + if (options != NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); + } + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + if (options == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pss_opts->mgf1_hash_id == md_alg) { + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + unsigned char *p; + int key_len; + size_t signature_length; + psa_status_t status = PSA_ERROR_DATA_CORRUPT; + psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; + + psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); + p = buf + sizeof(buf); + key_len = mbedtls_pk_write_pubkey(&p, buf, ctx); + + if (key_len < 0) { + return key_len; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_sig_alg); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + psa_destroy_key(key_id); + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH + * on a valid signature with trailing data in a buffer, but + * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, + * so for this reason the passed sig_len is overwritten. Smaller + * signature lengths should not be accepted for verification. */ + signature_length = sig_len > mbedtls_pk_get_len(ctx) ? + mbedtls_pk_get_len(ctx) : sig_len; + status = psa_verify_hash(key_id, psa_sig_alg, hash, + hash_len, sig, signature_length); + destruction_status = psa_destroy_key(key_id); + + if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + if (status == PSA_SUCCESS) { + status = destruction_status; + } + + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else +#endif + { + if (sig_len < mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig); + if (ret != 0) { + return ret; + } + + if (sig_len > mbedtls_pk_get_len(ctx)) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + return 0; + } +#else + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ +} + +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx) +{ + if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if (rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { + return ret; + } + + ret = ctx->pk_info->sign_rs_func(ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, rs_ctx->rs_ctx); + + if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { + mbedtls_pk_restart_free(rs_ctx); + } + + return ret; + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if (ctx->pk_info->sign_func == NULL) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + return ctx->pk_info->sign_func(ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, NULL); +} + +#if defined(MBEDTLS_PSA_CRYPTO_C) +/* + * Make a signature given a signature type. + */ +int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, + mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ +#if defined(MBEDTLS_RSA_C) + psa_algorithm_t psa_md_alg; +#endif /* MBEDTLS_RSA_C */ + *sig_len = 0; + + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (!mbedtls_pk_can_do(ctx, pk_type)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + if (pk_type != MBEDTLS_PK_RSASSA_PSS) { + return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, f_rng, p_rng); + } + +#if defined(MBEDTLS_RSA_C) + psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { + psa_status_t status; + + status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg), + hash, hash_len, + sig, sig_size, sig_len); + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + + return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), + ctx->pk_ctx, hash, hash_len, + sig, sig_size, sig_len); +#else /* MBEDTLS_RSA_C */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* !MBEDTLS_RSA_C */ + +} +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info->decrypt_func == NULL) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + return ctx->pk_info->decrypt_func(ctx, input, ilen, + output, olen, osize, f_rng, p_rng); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info->encrypt_func == NULL) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + return ctx->pk_info->encrypt_func(ctx, input, ilen, + output, olen, osize, f_rng, p_rng); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + if (pub->pk_info == NULL || + prv->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (f_rng == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (prv->pk_info->check_pair_func == NULL) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + + if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { + if (pub->pk_info->type != MBEDTLS_PK_RSA) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + } else { + if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) && + (pub->pk_info != prv->pk_info)) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + } + + return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub, + (mbedtls_pk_context *) prv, + f_rng, p_rng); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if (ctx == NULL || ctx->pk_info == NULL) { + return 0; + } + + return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) +{ + if (ctx->pk_info == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (ctx->pk_info->debug_func == NULL) { + return MBEDTLS_ERR_PK_TYPE_MISMATCH; + } + + ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items); + return 0; +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) +{ + if (ctx == NULL || ctx->pk_info == NULL) { + return "invalid PK"; + } + + return ctx->pk_info->name; +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) +{ + if (ctx == NULL || ctx->pk_info == NULL) { + return MBEDTLS_PK_NONE; + } + + return ctx->pk_info->type; +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Load the key to a PSA key slot, + * then turn the PK context into a wrapper for that key slot. + * + * Currently only works for EC & RSA private keys. + */ +int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, + mbedtls_svc_key_id_t *key, + psa_algorithm_t alg, + psa_key_usage_t usage, + psa_algorithm_t alg2) +{ +#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C) + ((void) pk); + ((void) key); + ((void) alg); + ((void) usage); + ((void) alg2); +#else /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { + size_t d_len; + psa_ecc_family_t curve_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + size_t bits; + psa_status_t status; + + /* export the private key material in the format PSA wants */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + unsigned char d[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; + status = psa_export_key(pk->priv_id, d, sizeof(d), &d_len); + if (status != PSA_SUCCESS) { + return psa_pk_status_to_mbedtls(status); + } + + curve_id = pk->ec_family; + bits = pk->ec_bits; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + unsigned char d[MBEDTLS_ECP_MAX_BYTES]; + mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + d_len = PSA_BITS_TO_BYTES(ec->grp.nbits); + if ((ret = mbedtls_ecp_write_key(ec, d, d_len)) != 0) { + return ret; + } + + curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); + + /* prepare the key attributes */ + psa_set_key_type(&attributes, key_type); + psa_set_key_bits(&attributes, bits); + psa_set_key_usage_flags(&attributes, usage); + psa_set_key_algorithm(&attributes, alg); + if (alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&attributes, alg2); + } + + /* import private key into PSA */ + status = psa_import_key(&attributes, d, d_len, key); + mbedtls_platform_zeroize(d, sizeof(d)); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* make PK context wrap the key slot */ + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + + return mbedtls_pk_setup_opaque(pk, *key); + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) { + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + int key_len; + psa_status_t status; + + /* export the private key material in the format PSA wants */ + key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* prepare the key attributes */ + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk)); + psa_set_key_usage_flags(&attributes, usage); + psa_set_key_algorithm(&attributes, alg); + if (alg2 != PSA_ALG_NONE) { + psa_set_key_enrollment_algorithm(&attributes, alg2); + } + + /* import private key into PSA */ + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, + key_len, key); + + mbedtls_platform_zeroize(buf, sizeof(buf)); + + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + /* make PK context wrap the key slot */ + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + + return mbedtls_pk_setup_opaque(pk, *key); + } else +#endif /* MBEDTLS_RSA_C */ +#endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ + return MBEDTLS_ERR_PK_TYPE_MISMATCH; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk_wrap.c b/matter/mbedtls/tinycrypt/src/pk_wrap.c new file mode 100644 index 0000000000..5b78dfb426 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/pk_wrap.c @@ -0,0 +1,1850 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * 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. + */ + +#include "common.h" + +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PK_C) +#include "pk_wrap.h" +#include "pk_internal.h" +#include "mbedtls/error.h" +#include "md_psa.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C) +#include "pkwrite.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa_util_internal.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +#include "mbedtls/asn1write.h" +#include "mbedtls/asn1.h" +#endif +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include "mbedtls/platform.h" + +#include +#include +#include + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_PSA_CRYPTO_C) +int mbedtls_pk_error_from_psa(psa_status_t status) +{ + switch (status) { + case PSA_SUCCESS: + return 0; + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + case PSA_ERROR_NOT_PERMITTED: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_PK_INVALID_ALG; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +int mbedtls_pk_error_from_psa_rsa(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_NOT_PERMITTED: + case PSA_ERROR_INVALID_ARGUMENT: + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return MBEDTLS_ERR_RSA_RNG_FAILED; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + case PSA_ERROR_INVALID_PADDING: + return MBEDTLS_ERR_RSA_INVALID_PADDING; + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status) +{ + switch (status) { + case PSA_ERROR_NOT_PERMITTED: + case PSA_ERROR_INVALID_ARGUMENT: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + case PSA_ERROR_INVALID_HANDLE: + return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + case PSA_ERROR_BUFFER_TOO_SMALL: + return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return MBEDTLS_ERR_ECP_RANDOM_FAILED; + case PSA_ERROR_INVALID_SIGNATURE: + return MBEDTLS_ERR_ECP_VERIFY_FAILED; + case PSA_SUCCESS: + return 0; + case PSA_ERROR_NOT_SUPPORTED: + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return MBEDTLS_ERR_PK_ALLOC_FAILED; + case PSA_ERROR_BAD_STATE: + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + case PSA_ERROR_DATA_CORRUPT: + case PSA_ERROR_DATA_INVALID: + case PSA_ERROR_STORAGE_FAILURE: + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + case PSA_ERROR_CORRUPTION_DETECTED: + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + default: + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; + } +} +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS; +} + +static size_t rsa_get_bitlen(mbedtls_pk_context *pk) +{ + const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx; + return 8 * mbedtls_rsa_get_len(rsa); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + psa_algorithm_t psa_alg_md = + PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); + size_t rsa_len = mbedtls_rsa_get_len(rsa); + + if (md_alg == MBEDTLS_MD_NONE +#if SIZE_MAX > UINT_MAX + && UINT_MAX < hash_len +#endif + ) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (sig_len < rsa_len) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + /* mbedtls_pk_write_pubkey_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = rsa; + key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_alg_md); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, + sig, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + size_t rsa_len = mbedtls_rsa_get_len(rsa); + +#if SIZE_MAX > UINT_MAX + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + if (sig_len < rsa_len) { + return MBEDTLS_ERR_RSA_VERIFY_FAILED; + } + + if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, + (unsigned int) hash_len, + hash, sig)) != 0) { + return ret; + } + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if (sig_len > rsa_len) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + return 0; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PSA_CRYPTO_C) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char *buf = NULL; + buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); + if (buf == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + mbedtls_pk_info_t pk_info = mbedtls_rsa_info; + + *sig_len = mbedtls_rsa_get_len(rsa_ctx); + if (sig_size < *sig_len) { + mbedtls_free(buf); + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + /* mbedtls_pk_write_key_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = rsa_ctx; + key_len = mbedtls_pk_write_key_der(&key, buf, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); + if (key_len <= 0) { + mbedtls_free(buf); + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, alg); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + + status = psa_import_key(&attributes, + buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + status = psa_sign_hash(key_id, alg, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_free(buf); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + return ret; +} +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + ((void) f_rng); + ((void) p_rng); + + psa_algorithm_t psa_md_alg; + psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); + if (psa_md_alg == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN( + psa_md_alg), + pk->pk_ctx, hash, hash_len, + sig, sig_size, sig_len); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + +#if SIZE_MAX > UINT_MAX + if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + *sig_len = mbedtls_rsa_get_len(rsa); + if (sig_size < *sig_len) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, + md_alg, (unsigned int) hash_len, + hash, sig); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_decrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; + + ((void) f_rng); + ((void) p_rng); + +#if !defined(MBEDTLS_RSA_ALT) + if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } +#endif /* !MBEDTLS_RSA_ALT */ + + if (ilen != mbedtls_rsa_get_len(rsa)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + /* mbedtls_pk_write_key_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = rsa; + key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_decrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + + if (ilen != mbedtls_rsa_get_len(rsa)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, + olen, input, output, osize); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int rsa_encrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; + + ((void) f_rng); + ((void) p_rng); + +#if !defined(MBEDTLS_RSA_ALT) + if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { + return MBEDTLS_ERR_RSA_INVALID_PADDING; + } +#endif + + if (mbedtls_rsa_get_len(rsa) > osize) { + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + } + + /* mbedtls_pk_write_pubkey_der() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &mbedtls_rsa_info; + key.pk_ctx = rsa; + key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); + if (key_len <= 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); + psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); + + status = psa_import_key(&attributes, + buf + sizeof(buf) - key_len, key_len, + &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int rsa_encrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + *olen = mbedtls_rsa_get_len(rsa); + + if (*olen > osize) { + return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + } + + return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, + ilen, input, output); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + (void) f_rng; + (void) p_rng; + return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx, + (const mbedtls_rsa_context *) prv->pk_ctx); +} + +static void *rsa_alloc_wrap(void) +{ + void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); + + if (ctx != NULL) { + mbedtls_rsa_init((mbedtls_rsa_context *) ctx); + } + + return ctx; +} + +static void rsa_free_wrap(void *ctx) +{ + mbedtls_rsa_free((mbedtls_rsa_context *) ctx); + mbedtls_free(ctx); +} + +static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) +{ +#if defined(MBEDTLS_RSA_ALT) + /* Not supported */ + (void) pk; + (void) items; +#else + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &(rsa->N); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &(rsa->E); +#endif +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + .type = MBEDTLS_PK_RSA, + .name = "RSA", + .get_bitlen = rsa_get_bitlen, + .can_do = rsa_can_do, + .verify_func = rsa_verify_wrap, + .sign_func = rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = rsa_decrypt_wrap, + .encrypt_func = rsa_encrypt_wrap, + .check_pair_func = rsa_check_pair_wrap, + .ctx_alloc_func = rsa_alloc_wrap, + .ctx_free_func = rsa_free_wrap, + .debug_func = rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/* + * Generic EC key + */ +static int eckey_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA; +} + +static size_t eckey_get_bitlen(mbedtls_pk_context *pk) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + return pk->ec_bits; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; + return ecp->grp.pbits; +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding expected by PSA. + */ +static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len; + + if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER)) != 0) { + return ret; + } + + while (unpadded_len > 0 && **from == 0x00) { + (*from)++; + unpadded_len--; + } + + if (unpadded_len > to_len || unpadded_len == 0) { + return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + + padding_len = to_len - unpadded_len; + memset(to, 0x00, padding_len); + memcpy(to + padding_len, *from, unpadded_len); + (*from) += unpadded_len; + + return 0; +} + +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tmp_size; + + if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return ret; + } + + /* Extract r */ + if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) { + return ret; + } + /* Extract s */ + if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) { + return ret; + } + + return 0; +} + +/* Common helper for ECDSA verify using PSA functions. */ +static int ecdsa_verify_psa(unsigned char *key, size_t key_len, + psa_ecc_family_t curve, size_t curve_bits, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits); + unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; + unsigned char *p; + psa_status_t status; + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&attributes, psa_sig_md); + + status = psa_import_key(&attributes, key, key_len, &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + if (signature_len > sizeof(extracted_sig)) { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + p = (unsigned char *) sig; + /* extract_ecdsa_sig's last parameter is the size + * of each integer to be parsed, so it's actually half + * the size of the signature. */ + if ((ret = extract_ecdsa_sig(&p, sig + sig_len, extracted_sig, + signature_len/2)) != 0) { + goto cleanup; + } + + status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len, + extracted_sig, signature_len); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + if (p != sig + sig_len) { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} + +static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t key_len; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_ecc_family_t curve; + size_t curve_bits; + psa_status_t status; + + status = psa_get_key_attributes(pk->priv_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr)); + curve_bits = psa_get_key_bits(&key_attr); + psa_reset_key_attributes(&key_attr); + + status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + + return ecdsa_verify_psa(key, key_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + psa_ecc_family_t curve = pk->ec_family; + size_t curve_bits = pk->ec_bits; + + return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + (void) md_alg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ctx = pk->pk_ctx; + unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t key_len; + size_t curve_bits; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); + + ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &key_len, key, sizeof(key)); + if (ret != 0) { + return ret; + } + + return ecdsa_verify_psa(key, key_len, curve, curve_bits, + hash, hash_len, sig, sig_len); +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx, + hash, hash_len, sig, sig_len); + + if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + return ret; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). + * + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start + */ +static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, + size_t n_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if ((size_t) (*p - start) < n_len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + len = n_len; + *p -= len; + memmove(*p, start, len); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of a PSA error. */ + while (len > 0 && **p == 0x00) { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if (len == 0) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if (**p & 0x80) { + if (*p - start < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, + MBEDTLS_ASN1_INTEGER)); + + return (int) len; +} + +/* Transcode signature from PSA format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer + */ +static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len, + size_t buf_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); + MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + memmove(sig, p, len); + *sig_len = len; + + return 0; +} + +/* Common helper for ECDSA sign using PSA functions. */ +static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_status_t status; + psa_algorithm_t psa_sig_md; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + + status = psa_get_key_attributes(key_id, &key_attr); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + alg = psa_get_key_algorithm(&key_attr); + psa_reset_key_attributes(&key_attr); + + if (PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)) { + psa_sig_md = PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); + } else { + psa_sig_md = PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); + } + + status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + } + + ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size); + + return ret; +} + +static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + ((void) f_rng); + ((void) p_rng); + + return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size, + sig_len); +} + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up + * using the same function. */ +#define ecdsa_sign_wrap ecdsa_opaque_sign_wrap +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_status_t status; + mbedtls_ecp_keypair *ctx = pk->pk_ctx; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); + size_t key_len = PSA_BITS_TO_BYTES(curve_bits); +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + psa_algorithm_t psa_sig_md = + PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); +#else + psa_algorithm_t psa_sig_md = + PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); +#endif + ((void) f_rng); + ((void) p_rng); + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + if (key_len > sizeof(buf)) { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); + if (ret != 0) { + goto cleanup; + } + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&attributes, psa_sig_md); + + status = psa_import_key(&attributes, buf, key_len, &key_id); + if (status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + goto cleanup; + } + + ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len); + +cleanup: + mbedtls_platform_zeroize(buf, sizeof(buf)); + status = psa_destroy_key(key_id); + if (ret == 0 && status != PSA_SUCCESS) { + ret = PSA_PK_TO_MBEDTLS_ERR(status); + } + + return ret; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx, + md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx); + +static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct { + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc(void) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); + + if (ctx != NULL) { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); + mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); + } + + return ctx; +} + +static void eckey_rs_free(void *ctx) +{ + eckey_restart_ctx *rs_ctx; + + if (ctx == NULL) { + return; + } + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); + mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); + + mbedtls_free(ctx); +} + +static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if (rs == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* set up our own sub-context if needed (that is, on first run) */ + if (rs->ecdsa_ctx.grp.pbits == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); + } + + MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs)); + +cleanup: + return ret; +} + +static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if (rs == NULL) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* set up our own sub-context if needed (that is, on first run) */ + if (rs->ecdsa_ctx.grp.pbits == 0) { + MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); + } + + MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg, + hash, hash_len, sig, sig_size, sig_len, + f_rng, p_rng, &rs->ecdsa_rs)); + +cleanup: + return ret; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t prv_key_len; + mbedtls_svc_key_id_t key_id = prv->priv_id; + + status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), + &prv_key_len); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + if (ret != 0) { + return ret; + } + + if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return 0; +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t prv_key_len; + psa_status_t destruction_status; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t pub_key_len; + size_t curve_bits; + const psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits); + const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits); + + if (curve == 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); + + ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d, + prv_key_buf, curve_bytes); + if (ret != 0) { + mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); + return ret; + } + + status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id); + mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + if (ret != 0) { + return ret; + } + + // From now on prv_key_buf is used to store the public key of prv. + status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), + &prv_key_len); + ret = PSA_PK_TO_MBEDTLS_ERR(status); + destruction_status = psa_destroy_key(key_id); + if (ret != 0) { + return ret; + } else if (destruction_status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(destruction_status); + } + + ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp, + &mbedtls_pk_ec_rw(*pub)->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &pub_key_len, pub_key_buf, + sizeof(pub_key_buf)); + if (ret != 0) { + return ret; + } + + if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + return 0; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + (void) f_rng; + (void) p_rng; + return eckey_check_pair_psa(pub, prv); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx, + (const mbedtls_ecp_keypair *) prv->pk_ctx, + f_rng, p_rng); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up + * using the same function. */ +#define ecdsa_opaque_check_pair_wrap eckey_check_pair_wrap +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub, + mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + psa_status_t status; + uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t exp_pub_key_len = 0; + uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; + size_t pub_key_len = 0; + int ret; + (void) f_rng; + (void) p_rng; + + status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key), + &exp_pub_key_len); + if (status != PSA_SUCCESS) { + ret = psa_pk_status_to_mbedtls(status); + return ret; + } + ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp), + &(mbedtls_pk_ec_ro(*pub)->Q), + MBEDTLS_ECP_PF_UNCOMPRESSED, + &pub_key_len, pub_key, sizeof(pub_key)); + if (ret != 0) { + return ret; + } + if ((exp_pub_key_len != pub_key_len) || + memcmp(exp_pub_key, pub_key, exp_pub_key_len)) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + return 0; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static void *eckey_alloc_wrap(void) +{ + void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); + + if (ctx != NULL) { + mbedtls_ecp_keypair_init(ctx); + } + + return ctx; +} + +static void eckey_free_wrap(void *ctx) +{ + mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); + mbedtls_free(ctx); +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) +{ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + items->type = MBEDTLS_PK_DEBUG_PSA_EC; + items->name = "eckey.Q"; + items->value = pk; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &(ecp->Q); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + .type = MBEDTLS_PK_ECKEY, + .name = "EC", + .get_bitlen = eckey_get_bitlen, + .can_do = eckey_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = eckey_verify_rs_wrap, + .sign_rs_func = eckey_sign_rs_wrap, + .rs_alloc_func = eckey_rs_alloc, + .rs_free_func = eckey_rs_free, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, + .ctx_free_func = eckey_free_wrap, +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH; +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + .type = MBEDTLS_PK_ECKEY_DH, + .name = "EC_DH", + .get_bitlen = eckey_get_bitlen, /* Same underlying key structure */ + .can_do = eckeydh_can_do, + .verify_func = NULL, + .sign_func = NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, /* Same underlying key structure */ + .ctx_free_func = eckey_free_wrap, /* Same underlying key structure */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, /* Same underlying key structure */ +}; + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +static int ecdsa_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECDSA; +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) pk->pk_ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx); + + if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { + return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + } + + return ret; +} + +static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx) +{ + return mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) pk->pk_ctx, + md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx); + +} + +static void *ecdsa_rs_alloc(void) +{ + void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); + + if (ctx != NULL) { + mbedtls_ecdsa_restart_init(ctx); + } + + return ctx; +} + +static void ecdsa_rs_free(void *ctx) +{ + mbedtls_ecdsa_restart_free(ctx); + mbedtls_free(ctx); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + .type = MBEDTLS_PK_ECDSA, + .name = "ECDSA", + .get_bitlen = eckey_get_bitlen, /* Compatible key structures */ + .can_do = ecdsa_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ +#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = ecdsa_verify_rs_wrap, + .sign_rs_func = ecdsa_sign_rs_wrap, + .rs_alloc_func = ecdsa_rs_alloc, + .rs_free_func = ecdsa_rs_free, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = eckey_check_pair_wrap, /* Compatible key structures */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .ctx_alloc_func = eckey_alloc_wrap, /* Compatible key structures */ + .ctx_free_func = eckey_free_wrap, /* Compatible key structures */ +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + .debug_func = eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_RSA; +} + +static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk) +{ + const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; + + return 8 * rsa_alt->key_len_func(rsa_alt->key); +} + +static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; + +#if SIZE_MAX > UINT_MAX + if (UINT_MAX < hash_len) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } +#endif + + *sig_len = rsa_alt->key_len_func(rsa_alt->key); + if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + if (*sig_len > sig_size) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + + return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, + md_alg, (unsigned int) hash_len, hash, sig); +} + +static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; + + ((void) f_rng); + ((void) p_rng); + + if (ilen != rsa_alt->key_len_func(rsa_alt->key)) { + return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + } + + return rsa_alt->decrypt_func(rsa_alt->key, + olen, input, output, osize); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) { + return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + memset(hash, 0x2a, sizeof(hash)); + + if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE, + hash, sizeof(hash), + sig, sizeof(sig), &sig_len, + f_rng, p_rng)) != 0) { + return ret; + } + + if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE, + hash, sizeof(hash), sig, sig_len) != 0) { + return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return 0; +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap(void) +{ + void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); + + if (ctx != NULL) { + memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); + } + + return ctx; +} + +static void rsa_alt_free_wrap(void *ctx) +{ + mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context)); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + .type = MBEDTLS_PK_RSA_ALT, + .name = "RSA-alt", + .get_bitlen = rsa_alt_get_bitlen, + .can_do = rsa_alt_can_do, + .verify_func = NULL, + .sign_func = rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = rsa_alt_decrypt_wrap, + .encrypt_func = NULL, +#if defined(MBEDTLS_RSA_C) + .check_pair_func = rsa_alt_check_pair, +#else + .check_pair_func = NULL, +#endif + .ctx_alloc_func = rsa_alt_alloc_wrap, + .ctx_free_func = rsa_alt_free_wrap, + .debug_func = NULL, +}; +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static size_t opaque_get_bitlen(mbedtls_pk_context *pk) +{ + size_t bits; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) { + return 0; + } + + bits = psa_get_key_bits(&attributes); + psa_reset_key_attributes(&attributes); + return bits; +} + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +static int ecdsa_opaque_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA; +} + +const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = { + .type = MBEDTLS_PK_OPAQUE, + .name = "Opaque", + .get_bitlen = opaque_get_bitlen, + .can_do = ecdsa_opaque_can_do, +#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) + .verify_func = ecdsa_opaque_verify_wrap, +#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ + .verify_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ +#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) + .sign_func = ecdsa_opaque_sign_wrap, +#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ + .sign_func = NULL, +#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + .decrypt_func = NULL, + .encrypt_func = NULL, + .check_pair_func = ecdsa_opaque_check_pair_wrap, + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, + .debug_func = NULL, +}; +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +static int rsa_opaque_can_do(mbedtls_pk_type_t type) +{ + return type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS; +} + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +static int rsa_opaque_decrypt(mbedtls_pk_context *pk, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + status = psa_asymmetric_decrypt(pk->priv_id, PSA_ALG_RSA_PKCS1V15_CRYPT, + input, ilen, + NULL, 0, + output, osize, olen); + if (status != PSA_SUCCESS) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } + + return 0; +} +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + +static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ +#if defined(MBEDTLS_RSA_C) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg; + psa_key_type_t type; + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + status = psa_get_key_attributes(pk->priv_id, &attributes); + if (status != PSA_SUCCESS) { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + + type = psa_get_key_type(&attributes); + psa_reset_key_attributes(&attributes); + + if (PSA_KEY_TYPE_IS_RSA(type)) { + alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); + } else { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + + /* make the signature */ + status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, + sig, sig_size, sig_len); + if (status != PSA_SUCCESS) { + if (PSA_KEY_TYPE_IS_RSA(type)) { + return PSA_PK_RSA_TO_MBEDTLS_ERR(status); + } else { + return PSA_PK_TO_MBEDTLS_ERR(status); + } + } + + return 0; +#else /* !MBEDTLS_RSA_C */ + ((void) pk); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_size); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* !MBEDTLS_RSA_C */ +} + +const mbedtls_pk_info_t mbedtls_rsa_opaque_info = { + .type = MBEDTLS_PK_OPAQUE, + .name = "Opaque", + .get_bitlen = opaque_get_bitlen, + .can_do = rsa_opaque_can_do, + .verify_func = NULL, + .sign_func = rsa_opaque_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + .verify_rs_func = NULL, + .sign_rs_func = NULL, + .rs_alloc_func = NULL, + .rs_free_func = NULL, +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) + .decrypt_func = rsa_opaque_decrypt, +#else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + .decrypt_func = NULL, +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ + .encrypt_func = NULL, + .check_pair_func = NULL, + .ctx_alloc_func = NULL, + .ctx_free_func = NULL, + .debug_func = NULL, +}; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk_wrap.h b/matter/mbedtls/tinycrypt/src/pk_wrap.h new file mode 100644 index 0000000000..b1e02180a5 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/pk_wrap.h @@ -0,0 +1,168 @@ +/** + * \file pk_wrap.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * 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. + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa/crypto.h" +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +struct mbedtls_pk_info_t { + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)(mbedtls_pk_context *pk); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)(mbedtls_pk_type_t type); + + /** Verify signature */ + int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len); + + /** Make signature */ + int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx); + + /** Make signature (restartable) */ + int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + + /** Encrypt message */ + int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + + /** Check public-private key pair */ + int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng); + + /** Allocate a new context */ + void * (*ctx_alloc_func)(void); + + /** Free the given context */ + void (*ctx_free_func)(void *ctx); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void *(*rs_alloc_func)(void); + + /** Free the restart context */ + void (*rs_free_func)(void *rs_ctx); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct { + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info; +extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info; + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status); +#endif +#endif + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status); + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ + defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status); +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_RSA_C) +int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, + mbedtls_rsa_context *rsa_ctx, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, + size_t *sig_len); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/matter/mbedtls/tinycrypt/src/pkparse.c b/matter/mbedtls/tinycrypt/src/pkparse.c new file mode 100644 index 0000000000..e1422df771 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/pkparse.c @@ -0,0 +1,1857 @@ +/* + * Public Key layer for parsing key files and structures + * + * 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. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "pk_internal.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#include "mbedtls/ecp.h" +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pk_internal.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +#include "psa_util_internal.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#include "mbedtls/platform.h" + +/* Helper for Montgomery curves */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) +#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \ + ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448)) +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && MBEDTLS_PK_HAVE_RFC8410_CURVES */ + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) +{ + FILE *f; + long size; + + if ((f = fopen(path, "rb")) == NULL) { + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + + /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ + mbedtls_setbuf(f, NULL); + + fseek(f, 0, SEEK_END); + if ((size = ftell(f)) == -1) { + fclose(f); + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + fseek(f, 0, SEEK_SET); + + *n = (size_t) size; + + if (*n + 1 == 0 || + (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { + fclose(f); + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + if (fread(*buf, 1, *n, f) != *n) { + fclose(f); + + mbedtls_zeroize_and_free(*buf, *n); + + return MBEDTLS_ERR_PK_FILE_IO_ERROR; + } + + fclose(f); + + (*buf)[*n] = '\0'; + + if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { + ++*n; + } + + return 0; +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, + const char *path, const char *pwd, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { + return ret; + } + + if (pwd == NULL) { + ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); + } else { + ret = mbedtls_pk_parse_key(ctx, buf, n, + (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); + } + + mbedtls_zeroize_and_free(buf, n); + + return ret; +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { + return ret; + } + + ret = mbedtls_pk_parse_public_key(ctx, buf, n); + + mbedtls_zeroize_and_free(buf, n); + + return ret; +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams(unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (end - *p < 1) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA); + } + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if (params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) +#endif + ) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + + if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + params->p = *p; + *p += params->len; + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = params->p; + const unsigned char *const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (ver < 1 || ver > 3) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return ret; + } + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { + return ret; + } + + if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || + memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + grp->pbits = mbedtls_mpi_bitlen(&grp->P); + + if (p != end_field) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return ret; + } + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || + (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + p += len; + + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || + (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { + p += len; + } + + if (p != end_curve) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * ECPoint ::= OCTET STRING + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, + (const unsigned char *) p, len)) != 0) { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + (p[0] != 0x02 && p[0] != 0x03) || + len != mbedtls_mpi_size(&grp->P) + 1 || + mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || + mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || + mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + } + + p += len; + + /* + * order INTEGER + */ + if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + grp->nbits = mbedtls_mpi_bitlen(&grp->N); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return 0; +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init(&ref); + + for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { + /* Load the group associated to that id */ + mbedtls_ecp_group_free(&ref); + MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); + + /* Compare to the group we were given, starting with easy tests */ + if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && + mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && + mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && + mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && + mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && + mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { + break; + } + } + +cleanup: + mbedtls_ecp_group_free(&ref); + + *grp_id = *id; + + if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + } + + return ret; +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init(&grp); + + if ((ret = pk_group_from_specified(params, &grp)) != 0) { + goto cleanup; + } + + ret = pk_group_id_from_group(&grp, grp_id); + +cleanup: + /* The API respecting lifecycle for mbedtls_ecp_group struct is + * _init(), _load() and _free(). In pk_group_id_from_specified() the + * temporary grp breaks that flow and it's members are populated + * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() + * which is assuming a group populated by _setup() may not clean-up + * properly -> Manually free it's members. + */ + mbedtls_mpi_free(&grp.N); + mbedtls_mpi_free(&grp.P); + mbedtls_mpi_free(&grp.A); + mbedtls_mpi_free(&grp.B); + mbedtls_ecp_point_free(&grp.G); + + return ret; +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +/* Functions pk_use_ecparams() and pk_use_ecparams_rfc8410() update the + * ecp_keypair structure with proper group ID. The purpose of this helper + * function is to update ec_family and ec_bits accordingly. */ +static int pk_update_psa_ecparams(mbedtls_pk_context *pk, + mbedtls_ecp_group_id grp_id) +{ + psa_ecc_family_t ec_family; + size_t bits; + + ec_family = mbedtls_ecc_group_to_psa(grp_id, &bits); + + if ((pk->ec_family != 0) && (pk->ec_family != ec_family)) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + pk->ec_family = ec_family; + pk->ec_bits = bits; + + return 0; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + + if (params->tag == MBEDTLS_ASN1_OID) { + if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { + return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; + } + } else { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) { + return ret; + } +#else + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; +#endif + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + ret = pk_update_psa_ecparams(pk, grp_id); +#else + /* grp may already be initialized; if so, make sure IDs match */ + if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && + mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + if ((ret = mbedtls_ecp_group_load(&(mbedtls_pk_ec_rw(*pk)->grp), + grp_id)) != 0) { + return ret; + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + return ret; +} + +/* + * Helper function for deriving a public key from its private counterpart. + */ +static int pk_derive_public_key(mbedtls_pk_context *pk, + const unsigned char *d, size_t d_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + (void) f_rng; + (void) p_rng; +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + (void) d; + (void) d_len; + + status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), + &pk->pub_raw_len); + ret = psa_pk_status_to_mbedtls(status); +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; + unsigned char key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t key_len; + mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + size_t curve_bits; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); + psa_status_t destruction_status; + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); + + status = psa_import_key(&key_attr, d, d_len, &key_id); + ret = psa_pk_status_to_mbedtls(status); + if (ret != 0) { + return ret; + } + + status = psa_export_public_key(key_id, key_buf, sizeof(key_buf), &key_len); + ret = psa_pk_status_to_mbedtls(status); + destruction_status = psa_destroy_key(key_id); + if (ret != 0) { + return ret; + } else if (destruction_status != PSA_SUCCESS) { + return psa_pk_status_to_mbedtls(destruction_status); + } + ret = mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, key_buf, key_len); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#else /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; + (void) d; + (void) d_len; + + ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return ret; +} + +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + +/* + * Load an RFC8410 EC key, which doesn't have any parameters + */ +static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id grp_id, + mbedtls_pk_context *pk) +{ + int ret; + + if (params->tag != 0 || params->len != 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + ret = pk_update_psa_ecparams(pk, grp_id); +#else + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); + ret = mbedtls_ecp_group_load(&(ecp->grp), grp_id); + if (ret != 0) { + return ret; + } +#endif + return ret; +} + +/* + * Parse an RFC 8410 encoded private EC key + * + * CurvePrivateKey ::= OCTET STRING + */ +static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (key + len != end) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_DERIVE); + psa_set_key_algorithm(&attributes, PSA_ALG_ECDH); + + status = psa_import_key(&attributes, key, len, &pk->priv_id); + if (status != PSA_SUCCESS) { + ret = psa_pk_status_to_mbedtls(status); + return ret; + } +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); + + if ((ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, + * which never contain a public key. As such, derive the public key + * unconditionally. */ + if ((ret = pk_derive_public_key(pk, key, len, f_rng, p_rng)) != 0) { + return ret; + } + + return 0; +} +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) && defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) +/* + * Create a temporary ecp_keypair for converting an EC point in compressed + * format to an uncompressed one + */ +static int pk_convert_compressed_ec(mbedtls_pk_context *pk, + const unsigned char *in_start, size_t in_len, + size_t *out_buf_len, unsigned char *out_buf, + size_t out_buf_size) +{ + mbedtls_ecp_keypair ecp_key; + mbedtls_ecp_group_id ecp_group_id; + int ret; + + ecp_group_id = mbedtls_ecc_group_of_psa(pk->ec_family, pk->ec_bits, 0); + + mbedtls_ecp_keypair_init(&ecp_key); + ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); + if (ret != 0) { + return ret; + } + ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, + in_start, in_len); + if (ret != 0) { + goto exit; + } + ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + out_buf_len, out_buf, out_buf_size); + +exit: + mbedtls_ecp_keypair_free(&ecp_key); + return ret; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA && MBEDTLS_PK_PARSE_EC_COMPRESSED */ + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + mbedtls_svc_key_id_t key; + psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; + size_t len = (end - *p); + + if (len > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + /* Compressed point format are not supported yet by PSA crypto. As a + * consequence ecp functions are used to "convert" the point to + * uncompressed format */ + if ((**p == 0x02) || (**p == 0x03)) { +#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) + ret = pk_convert_compressed_ec(pk, *p, len, + &(pk->pub_raw_len), pk->pub_raw, + PSA_EXPORT_PUBLIC_KEY_MAX_SIZE); + if (ret != 0) { + return ret; + } +#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ + } else { + /* Uncompressed format */ + if ((size_t) (end - *p) > MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN) { + return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + } + memcpy(pk->pub_raw, *p, (end - *p)); + pk->pub_raw_len = end - *p; + } + + /* Validate the key by trying to importing it */ + psa_set_key_usage_flags(&key_attrs, 0); + psa_set_key_algorithm(&key_attrs, PSA_ALG_ECDSA_ANY); + psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); + psa_set_key_bits(&key_attrs, pk->ec_bits); + + if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, + &key) != PSA_SUCCESS) || + (psa_destroy_key(key) != PSA_SUCCESS)) { + mbedtls_platform_zeroize(pk->pub_raw, MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN); + pk->pub_raw_len = 0; + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + ret = 0; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; + if ((ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, + (const unsigned char *) *p, + end - *p)) == 0) { + ret = mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return ret; +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey(unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + } + + if (*p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* Import N */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + } + + if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0)) != 0) { + return MBEDTLS_ERR_PK_INVALID_PUBKEY; + } + + *p += len; + + /* Import E */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + } + + if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len)) != 0) { + return MBEDTLS_ERR_PK_INVALID_PUBKEY; + } + + *p += len; + + if (mbedtls_rsa_complete(rsa) != 0 || + mbedtls_rsa_check_pubkey(rsa) != 0) { + return MBEDTLS_ERR_PK_INVALID_PUBKEY; + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg(unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *ec_grp_id) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf alg_oid; + + memset(params, 0, sizeof(mbedtls_asn1_buf)); + + if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); + } + + ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { + ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); + if (ret == 0) { + *pk_alg = MBEDTLS_PK_ECKEY; + } + } +#else + (void) ec_grp_id; +#endif + if (ret != 0) { + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + } + + /* + * No parameters with RSA (only for EC) + */ + if (*pk_alg == MBEDTLS_PK_RSA && + ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || + params->len != 0)) { + return MBEDTLS_ERR_PK_INVALID_ALG; + } + + return 0; +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; + const mbedtls_pk_info_t *pk_info; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + end = *p + len; + + if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { + return ret; + } + + if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); + } + + if (*p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + } + + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { + return ret; + } + +#if defined(MBEDTLS_RSA_C) + if (pk_alg == MBEDTLS_PK_RSA) { + ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { + ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); + } else +#endif + { + ret = pk_use_ecparams(&alg_params, pk); + } + if (ret == 0) { + ret = pk_get_ecpubkey(p, end, pk); + } + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if (ret == 0 && *p != end) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if (ret != 0) { + mbedtls_pk_free(pk); + } + + return ret; +} + +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi(unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X) +{ + int ret; + + ret = mbedtls_asn1_get_mpi(p, end, X); + if (ret != 0) { + return ret; + } + + if (mbedtls_mpi_cmp_int(X, 0) == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + return 0; +} + +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init(&T); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + end = p + len; + + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (version != 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; + } + + /* Import N */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, + NULL, NULL)) != 0) { + goto cleanup; + } + + /* Import E */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, + NULL, &T)) != 0) { + goto cleanup; + } + + /* Import D */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, + &T, NULL)) != 0) { + goto cleanup; + } + + /* Import P */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, + NULL, NULL)) != 0) { + goto cleanup; + } + + /* Import Q */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, + NULL, NULL)) != 0) { + goto cleanup; + } + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { + goto cleanup; + } + + /* Import DQ */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { + goto cleanup; + } + + /* Import QP */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { + goto cleanup; + } + +#else + /* Verify existence of the CRT params */ + if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || + (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { + goto cleanup; + } +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if ((ret = mbedtls_rsa_complete(rsa)) != 0 || + (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { + goto cleanup; + } + + if (p != end) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + +cleanup: + + mbedtls_mpi_free(&T); + + if (ret != 0) { + /* Wrap error code if it's coming from a lower level */ + if ((ret & 0xff80) == 0) { + ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } else { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + + mbedtls_rsa_free(rsa); + } + + return ret; +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der(mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len, d_len; + mbedtls_asn1_buf params = { 0, 0, NULL }; + unsigned char *p = (unsigned char *) key; + unsigned char *d; + unsigned char *end = p + keylen; + unsigned char *end2; +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ + mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + end = p + len; + + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (version != 1) { + return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + /* Keep a reference to the position fo the private key. It will be used + * later in this function. */ + d = p; + d_len = len; + + p += len; + + pubkey_done = 0; + if (p != end) { + /* + * Is 'parameters' present? + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + 0)) == 0) { + if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || + (ret = pk_use_ecparams(¶ms, pk)) != 0) { + return ret; + } + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + } + + +#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) + if ((ret = mbedtls_ecp_read_key(eck->grp.id, eck, d, d_len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } +#endif + + if (p != end) { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + 1)) == 0) { + end2 = p + len; + + if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (p + len != end2) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + if ((ret = pk_get_ecpubkey(&p, end2, pk)) == 0) { + pubkey_done = 1; + } else { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + } + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + } + +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); + /* Setting largest masks for usage and key algorithms */ + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE); +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + psa_set_key_algorithm(&attributes, + PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH)); +#else + psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)); +#endif + psa_set_key_enrollment_algorithm(&attributes, PSA_ALG_ECDH); + + status = psa_import_key(&attributes, d, d_len, &pk->priv_id); + if (status != PSA_SUCCESS) { + ret = psa_pk_status_to_mbedtls(status); + return ret; + } +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + + if (!pubkey_done) { + if ((ret = pk_derive_public_key(pk, d, d_len, f_rng, p_rng)) != 0) { + return ret; + } + } + + return 0; +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; + const mbedtls_pk_info_t *pk_info; + +#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) + (void) f_rng; + (void) p_rng; +#endif + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + end = p + len; + + if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (version != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); + } + + if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { + return ret; + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if (len < 1) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA); + } + + if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + } + + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { + return ret; + } + +#if defined(MBEDTLS_RSA_C) + if (pk_alg == MBEDTLS_PK_RSA) { + if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { + mbedtls_pk_free(pk); + return ret; + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { + if ((ret = + pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || + (ret = + pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, + p_rng)) != 0) { + mbedtls_pk_free(pk); + return ret; + } + } else +#endif + { + if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || + (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { + mbedtls_pk_free(pk); + return ret; + } + } + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + end = p + len; + if (end != (key + keylen)) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + size_t outlen = 0; + + p = key; + end = p + keylen; + + if (pwdlen == 0) { + return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; + } + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + end = p + len; + + if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); + } + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { + if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { + if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } + + return ret; + } + + decrypted = 1; + } else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { + if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf, len, &outlen)) != 0) { + if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } + + return ret; + } + + decrypted = 1; + } else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if (decrypted == 0) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } + return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key(mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + if (keylen == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init(&pem); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len); + } + + if (ret == 0) { + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), + pem.buf, pem.buflen)) != 0) { + mbedtls_pk_free(pk); + } + + mbedtls_pem_free(&pem); + return ret; + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len); + } + if (ret == 0) { + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); + + if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || + (ret = pk_parse_key_sec1_der(pk, + pem.buf, pem.buflen, + f_rng, p_rng)) != 0) { + mbedtls_pk_free(pk); + } + + mbedtls_pem_free(&pem); + return ret; + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { + return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; + } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { + return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len); + } + if (ret == 0) { + if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, + pem.buf, pem.buflen, f_rng, p_rng)) != 0) { + mbedtls_pk_free(pk); + } + + mbedtls_pem_free(&pem); + return ret; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len); + } + if (ret == 0) { + if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, + pwd, pwdlen, f_rng, p_rng)) != 0) { + mbedtls_pk_free(pk); + } + + mbedtls_pem_free(&pem); + return ret; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + return ret; + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + if (pwdlen != 0) { + unsigned char *key_copy; + + if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { + return MBEDTLS_ERR_PK_ALLOC_FAILED; + } + + memcpy(key_copy, key, keylen); + + ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, + pwd, pwdlen, f_rng, p_rng); + + mbedtls_zeroize_and_free(key_copy, keylen); + } + + if (ret == 0) { + return 0; + } + + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + + if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { + return ret; + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); + if (ret == 0) { + return 0; + } + + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); + if (mbedtls_pk_setup(pk, pk_info) == 0 && + pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) { + return 0; + } + + mbedtls_pk_free(pk); + mbedtls_pk_init(pk); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); + if (mbedtls_pk_setup(pk, pk_info) == 0 && + pk_parse_key_sec1_der(pk, + key, keylen, f_rng, p_rng) == 0) { + return 0; + } + mbedtls_pk_free(pk); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + if (keylen == 0) { + return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + } + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init(&pem); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len); + } + + if (ret == 0) { + p = pem.buf; + if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { + mbedtls_pem_free(&pem); + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + } + + if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { + mbedtls_pem_free(&pem); + return ret; + } + + if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) { + mbedtls_pk_free(ctx); + } + + mbedtls_pem_free(&pem); + return ret; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + mbedtls_pem_free(&pem); + return ret; + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if (key[keylen - 1] != '\0') { + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + } else { + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len); + } + + if (ret == 0) { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); + mbedtls_pem_free(&pem); + return ret; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + mbedtls_pem_free(&pem); + return ret; + } + mbedtls_pem_free(&pem); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { + return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + } + + if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { + return ret; + } + + p = (unsigned char *) key; + ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx)); + if (ret == 0) { + return ret; + } + mbedtls_pk_free(ctx); + if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) { + return ret; + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); + + return ret; +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/pkwrite.c b/matter/mbedtls/tinycrypt/src/pkwrite.c new file mode 100644 index 0000000000..03db1454aa --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/pkwrite.c @@ -0,0 +1,848 @@ +/* + * Public Key layer for writing key files and structures + * + * 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. + */ + +#include "common.h" + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "pk_internal.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pk_internal.h" +#endif +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#include "pkwrite.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "psa_util_internal.h" +#endif +#include "mbedtls/platform.h" + +/* Helper for Montgomery curves */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) +static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk) +{ + mbedtls_ecp_group_id id = mbedtls_pk_get_group_id(pk); + +#if defined(MBEDTLS_ECP_HAVE_CURVE25519) + if (id == MBEDTLS_ECP_DP_CURVE25519) { + return 1; + } +#endif +#if defined(MBEDTLS_ECP_HAVE_CURVE448) + if (id == MBEDTLS_ECP_DP_CURVE448) { + return 1; + } +#endif + return 0; +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PEM_WRITE_C) +/* It is assumed that the input key is opaque */ +static psa_ecc_family_t pk_get_opaque_ec_family(const mbedtls_pk_context *pk) +{ + psa_ecc_family_t ec_family = 0; + psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; + + if (psa_get_key_attributes(pk->priv_id, &key_attrs) != PSA_SUCCESS) { + return 0; + } + ec_family = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attrs)); + psa_reset_key_attributes(&key_attrs); + + return ec_family; +} +#endif /* MBETLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* It is assumed that the input key is opaque */ +static psa_key_type_t pk_get_opaque_key_type(const mbedtls_pk_context *pk) +{ + psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t opaque_key_type; + + if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { + return 0; + } + opaque_key_type = psa_get_key_type(&opaque_attrs); + psa_reset_key_attributes(&opaque_attrs); + + return opaque_key_type; +} +#endif /* MBETLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_mpi T; + mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); + + mbedtls_mpi_init(&T); + + /* Export E */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export N */ + if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { + goto end_of_export; + } + len += ret; + +end_of_export: + + mbedtls_mpi_free(&T); + if (ret < 0) { + return ret; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; + + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + } else { + len = pk->pub_raw_len; + memcpy(buf, pk->pub_raw, len); + } + + if (*p < start || (size_t) (*p - start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + *p -= len; + memcpy(*p, buf, len); + + return (int) len; +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t len = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; +#else + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + *p -= len; + memcpy(*p, buf, len); + return (int) len; + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof(buf))) != 0) { + return ret; + } + } + + if (*p < start || (size_t) (*p - start) < len) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + *p -= len; + memcpy(*p, buf, len); + + return (int) len; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param(unsigned char **p, unsigned char *start, + mbedtls_ecp_group_id grp_id) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid; + size_t oid_len; + + if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) { + return ret; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); + + return (int) len; +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) +static int pk_write_ec_private(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t byte_length; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; + psa_status_t status; + + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + goto exit; + } + } + + ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); +exit: + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return ret; +} +#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ +static int pk_write_ec_private(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t byte_length; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; + psa_status_t status; +#else + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); + if (status != PSA_SUCCESS) { + ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); + return ret; + } + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); + byte_length = (ec->grp.pbits + 7) / 8; + + ret = mbedtls_ecp_write_key(ec, tmp, byte_length); + if (ret != 0) { + goto exit; + } + } + ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); +exit: + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + return ret; +} +#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *pk) +{ + size_t buffer_size; + size_t len = 0; + + if (*p < start) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + buffer_size = (size_t) (*p - start); + if (psa_export_public_key(pk->priv_id, start, buffer_size, + &len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + + *p -= len; + memmove(*p, start, len); + + return (int) len; +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { + MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key)); + } else +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); + } else +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { + MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key)); + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + + return (int) len; +} + +int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + int has_par = 1; + size_t len = 0, par_len = 0, oid_len = 0; + mbedtls_pk_type_t pk_type; +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; +#endif + const char *oid = NULL; + + if (size == 0) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); + + if (c - buf < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); + + pk_type = mbedtls_pk_get_type(key); +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_type == MBEDTLS_PK_ECKEY) { + ec_grp_id = mbedtls_pk_get_group_id(key); + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (pk_type == MBEDTLS_PK_OPAQUE) { + psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key); +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { + pk_type = MBEDTLS_PK_ECKEY; + ec_grp_id = mbedtls_pk_get_group_id(key); + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { + /* The rest of the function works as for legacy RSA contexts. */ + pk_type = MBEDTLS_PK_RSA; + } + } + /* `pk_type` will have been changed to non-opaque by here if this function can handle it */ + if (pk_type == MBEDTLS_PK_OPAQUE) { + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_type == MBEDTLS_PK_ECKEY) { + /* Some groups have their own AlgorithmIdentifier OID, others are handled + * by mbedtls_oid_get_oid_by_pk_alg() below */ + ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len); + + if (ret == 0) { + /* Currently, none of the supported algorithms that have their own + * AlgorithmIdentifier OID have any parameters */ + has_par = 0; + } else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { + MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id)); + } else { + return ret; + } + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + if (oid_len == 0) { + if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, + &oid_len)) != 0) { + return ret; + } + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len, + par_len, has_par)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) +/* + * RFC8410 section 7 + * + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], + * ... + * } + * ... + * CurvePrivateKey ::= OCTET STRING + */ +static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + size_t oid_len = 0; + const char *oid; + mbedtls_ecp_group_id grp_id; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); + + grp_id = mbedtls_pk_get_group_id(pk); + /* privateKeyAlgorithm */ + if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) { + return ret; + } + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0)); + + /* version */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + +/* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ +static int pk_write_ec_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + int ret; + size_t pub_len = 0, par_len = 0; + mbedtls_ecp_group_id grp_id; + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk)); + + if (*p - buf < 1) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + (*p)--; + **p = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); + + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1)); + len += pub_len; + + /* parameters */ + grp_id = mbedtls_pk_get_group_id(pk); + MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id)); + MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len)); + MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0)); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); + + /* version */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + + return (int) len; +} +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + +#if defined(MBEDTLS_RSA_C) +static int pk_write_rsa_der(unsigned char **p, unsigned char *buf, + const mbedtls_pk_context *pk) +{ + size_t len = 0; + int ret; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { + uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; + size_t tmp_len = 0; + + if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PK_BAD_INPUT_DATA; + } + *p -= tmp_len; + memcpy(*p, tmp, tmp_len); + len += tmp_len; + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + } else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init(&T); + + /* Export QP */ + if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export DQ */ + if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export DP */ + if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export Q */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, + &T, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export P */ + if ((ret = mbedtls_rsa_export(rsa, NULL, &T, + NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export D */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, + NULL, &T, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export E */ + if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, + NULL, NULL, &T)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + + /* Export N */ + if ((ret = mbedtls_rsa_export(rsa, &T, NULL, + NULL, NULL, NULL)) != 0 || + (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { + goto end_of_export; + } + len += ret; + +end_of_export: + + mbedtls_mpi_free(&T); + if (ret < 0) { + return ret; + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE)); + } + + return (int) len; +} +#endif /* MBEDTLS_RSA_C */ + +int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + unsigned char *c; +#if defined(MBEDTLS_RSA_C) + int is_rsa_opaque = 0; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + int is_ec_opaque = 0; +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t opaque_key_type; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (size == 0) { + return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; + } + + c = buf + size; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { + opaque_key_type = pk_get_opaque_key_type(key); +#if defined(MBEDTLS_RSA_C) + is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type); +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type); +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_RSA_C) + if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) { + return pk_write_rsa_der(&c, buf, key); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (mbedtls_pk_is_rfc8410(key)) { + return pk_write_ec_rfc8410_der(&c, buf, key); + } +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + return pk_write_ec_der(&c, buf, key); + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n" + +#define PUB_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) +#define PRV_DER_MAX_BYTES \ + (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) + +int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, + sizeof(output_buf))) < 0) { + return ret; + } + + if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen)) != 0) { + return ret; + } + + return 0; +} + +int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + int is_ec_opaque = 0; +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + int is_montgomery_opaque = 0; +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ +#if defined(MBEDTLS_RSA_C) + int is_rsa_opaque = 0; +#endif + + if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { + return ret; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { + psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key); + +#if defined(MBEDTLS_RSA_C) + is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type); +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type); +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (pk_get_opaque_ec_family(key) == PSA_ECC_FAMILY_MONTGOMERY) { + is_montgomery_opaque = 1; + } +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_RSA_C) + if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } else +#endif +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) { +#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) + if (is_montgomery_opaque || + ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) && + (mbedtls_pk_is_rfc8410(key)))) { + begin = PEM_BEGIN_PRIVATE_KEY_PKCS8; + end = PEM_END_PRIVATE_KEY_PKCS8; + } else +#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + } else +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; + + if ((ret = mbedtls_pem_write_buffer(begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen)) != 0) { + return ret; + } + + return 0; +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c index 2175f563ea..b682394f7d 100644 --- a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c +++ b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c @@ -19,12 +19,13 @@ */ // This files is not part of the tinycript librairy. It is used to define function tinycript requires that are not present in the Simplicity SDK mbedtls fork +#include -#include "mbedtls/platform_util.h" +#include #include #if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) -#include "platform_fault.h" +#include #else static void mbedtls_platform_fault() { diff --git a/matter/mbedtls/tinycrypt/src/x509_crt.c b/matter/mbedtls/tinycrypt/src/x509_crt.c new file mode 100644 index 0000000000..7a63140d6f --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/x509_crt.c @@ -0,0 +1,3308 @@ +/* + * X.509 certificate parsing and verification + * + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "psa_util_internal.h" +#include "md_psa.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#include "pk_internal.h" + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#endif +#endif + +#if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#if defined(__MBED__) +#include +#else +#include +#endif /* __MBED__ */ +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif +#endif + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) + +/* Default profile. Do not remove items unless there are serious security + * concerns. */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + /* Curves at or above 128-bit security level. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | + 0, +#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 2048, +}; + +/* Next-generation profile. Currently identical to the default, but may + * be tightened at any time. */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above. */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level. */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), +#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + 0, +}; + +/* + * Empty / all-forbidden profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = +{ + 0, + 0, + 0, + (uint32_t) -1, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg) +{ + if (md_alg == MBEDTLS_MD_NONE) { + return -1; + } + + if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) { + return 0; + } + + return -1; +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg) +{ + if (pk_alg == MBEDTLS_PK_NONE) { + return -1; + } + + if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) { + return 0; + } + + return -1; +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk); + +#if defined(MBEDTLS_RSA_C) + if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) { + if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) { + return 0; + } + + return -1; + } +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) + if (pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH) { + const mbedtls_ecp_group_id gid = mbedtls_pk_get_group_id(pk); + + if (gid == MBEDTLS_ECP_DP_NONE) { + return -1; + } + + if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) { + return 0; + } + + return -1; + } +#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ + + return -1; +} + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp(const void *s1, const void *s2, size_t len) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for (i = 0; i < len; i++) { + diff = n1[i] ^ n2[i]; + + if (diff == 0) { + continue; + } + + if (diff == 32 && + ((n1[i] >= 'a' && n1[i] <= 'z') || + (n1[i] >= 'A' && n1[i] <= 'Z'))) { + continue; + } + + return -1; + } + + return 0; +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen(cn); + + /* We can't have a match if there is no wildcard to match */ + if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') { + return -1; + } + + for (i = 0; i < cn_len; ++i) { + if (cn[i] == '.') { + cn_idx = i; + break; + } + } + + if (cn_idx == 0) { + return -1; + } + + if (cn_len - cn_idx == name->len - 1 && + x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) { + return 0; + } + + return -1; +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b) +{ + if (a->tag == b->tag && + a->len == b->len && + memcmp(a->p, b->p, b->len) == 0) { + return 0; + } + + if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && + (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && + a->len == b->len && + x509_memcasecmp(a->p, b->p, b->len) == 0) { + return 0; + } + + return -1; +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while (a != NULL || b != NULL) { + if (a == NULL || b == NULL) { + return -1; + } + + /* type */ + if (a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) { + return -1; + } + + /* value */ + if (x509_string_cmp(&a->val, &b->val) != 0) { + return -1; + } + + /* structure of the list of sets */ + if (a->next_merged != b->next_merged) { + return -1; + } + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return 0; +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain) +{ + size_t i; + + for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + ver_chain->trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version(unsigned char **p, + const unsigned char *end, + int *ver) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + 0)) != 0) { + if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + *ver = 0; + return 0; + } + + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); + } + + end = *p + len; + + if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates(unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); + } + + end = *p + len; + + if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) { + return ret; + } + + if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) { + return ret; + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid(unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if (*p == end) { + return 0; + } + + uid->tag = **p; + + if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + n)) != 0) { + if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return 0; + } + + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); + } + + uid->p = *p; + *p += uid->len; + + return 0; +} + +static int x509_get_basic_constraints(unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p == end) { + return 0; + } + + if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { + if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + ret = mbedtls_asn1_get_int(p, end, ca_istrue); + } + + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*ca_istrue != 0) { + *ca_istrue = 1; + } + } + + if (*p == end) { + return 0; + } + + if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if (*max_pathlen == INT_MAX) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH); + } + + (*max_pathlen)++; + + return 0; +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + /* Sequence length must be >= 1 */ + if (ext_key_usage->buf.p == NULL) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH); + } + + return 0; +} + +/* + * SubjectKeyIdentifier ::= KeyIdentifier + * + * KeyIdentifier ::= OCTET STRING + */ +static int x509_get_subject_key_id(unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *subject_key_id) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0u; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + subject_key_id->len = len; + subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING; + subject_key_id->p = *p; + *p += len; + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * AuthorityKeyIdentifier ::= SEQUENCE { + * keyIdentifier [0] KeyIdentifier OPTIONAL, + * authorityCertIssuer [1] GeneralNames OPTIONAL, + * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + * + * KeyIdentifier ::= OCTET STRING + */ +static int x509_get_authority_key_id(unsigned char **p, + unsigned char *end, + mbedtls_x509_authority *authority_key_id) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0u; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC); + + /* KeyIdentifier is an OPTIONAL field */ + if (ret == 0) { + authority_key_id->keyIdentifier.len = len; + authority_key_id->keyIdentifier.p = *p; + /* Setting tag of the keyIdentfier intentionally to 0x04. + * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL), + * its tag with the content is the payload of on OCTET STRING primitive */ + authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; + + *p += len; + } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p < end) { + /* Getting authorityCertIssuer using the required specific class tag [1] */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | + 1)) != 0) { + /* authorityCertIssuer and authorityCertSerialNumber MUST both + be present or both be absent. At this point we expect to have both. */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + /* "end" also includes the CertSerialNumber field so "len" shall be used */ + ret = mbedtls_x509_get_subject_alt_name_ext(p, + (*p+len), + &authority_key_id->authorityCertIssuer); + if (ret != 0) { + return ret; + } + + /* Getting authorityCertSerialNumber using the required specific class tag [2] */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + authority_key_id->authorityCertSerialNumber.len = len; + authority_key_id->authorityCertSerialNumber.p = *p; + authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER; + *p += len; + } + + if (*p != end) { + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + } + + return 0; +} + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL } + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * ia5String IA5String (SIZE (1..200)), + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * NOTE: we only parse and use anyPolicy without qualifiers at this point + * as defined in RFC 5280. + */ +static int x509_get_certificate_policies(unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *certificate_policies) +{ + int ret, parse_ret = 0; + size_t len; + mbedtls_asn1_buf *buf; + mbedtls_asn1_sequence *cur = certificate_policies; + + /* Get main sequence tag */ + ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + if (*p + len != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * Cannot be an empty sequence. + */ + if (len == 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + while (*p < end) { + mbedtls_x509_buf policy_oid; + const unsigned char *policy_end; + + /* + * Get the policy sequence + */ + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + policy_end = *p + len; + + if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + policy_oid.tag = MBEDTLS_ASN1_OID; + policy_oid.len = len; + policy_oid.p = *p; + + /* + * Only AnyPolicy is currently supported when enforcing policy. + */ + if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { + /* + * Set the parsing return code but continue parsing, in case this + * extension is critical. + */ + parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + + /* Allocate and assign next pointer */ + if (cur->buf.p != NULL) { + if (cur->next != NULL) { + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; + } + + cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); + + if (cur->next == NULL) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED); + } + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = policy_oid.tag; + buf->p = policy_oid.p; + buf->len = policy_oid.len; + + *p += len; + + /* + * If there is an optional qualifier, then *p < policy_end + * Check the Qualifier len to verify it doesn't exceed policy_end. + */ + if (*p < policy_end) { + if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != + 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + /* + * Skip the optional policy qualifiers. + */ + *p += len; + } + + if (*p != policy_end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return parse_ret; +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext(unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; + + if (*p == end) { + return 0; + } + + if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) { + return ret; + } + + end = crt->v3_ext.p + crt->v3_ext.len; + while (*p < end) { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = { 0, 0, NULL }; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if ((ret = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + end_ext_data = *p + len; + + /* Get extension ID */ + if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && + (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + /* Data should be octet string type */ + if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING)) != 0) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } + + start_ext_octet = *p; + end_ext_octet = *p + len; + + if (end_ext_octet != end_ext_data) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); + + if (ret != 0) { + /* Give the callback (if any) a chance to handle the extension */ + if (cb != NULL) { + ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet); + if (ret != 0 && is_critical) { + return ret; + } + *p = end_ext_octet; + continue; + } + + /* No parser found, skip extension */ + *p = end_ext_octet; + + if (is_critical) { + /* Data is marked as critical: fail */ + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); + } + continue; + } + + /* Forbid repeated extensions */ + if ((crt->ext_types & ext_type) != 0) { + return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; + } + + crt->ext_types |= ext_type; + + switch (ext_type) { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if ((ret = x509_get_basic_constraints(p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet, + &crt->key_usage)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if ((ret = x509_get_ext_key_usage(p, end_ext_octet, + &crt->ext_key_usage)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: + /* Parse subject key identifier */ + if ((ret = x509_get_subject_key_id(p, end_ext_data, + &crt->subject_key_id)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: + /* Parse authority key identifier */ + if ((ret = x509_get_authority_key_id(p, end_ext_octet, + &crt->authority_key_id)) != 0) { + return ret; + } + break; + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name + * SubjectAltName ::= GeneralNames + */ + if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet, + &crt->subject_alt_names)) != 0) { + return ret; + } + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet, + &crt->ns_cert_type)) != 0) { + return ret; + } + break; + + case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: + /* Parse certificate policies type */ + if ((ret = x509_get_certificate_policies(p, end_ext_octet, + &crt->certificate_policies)) != 0) { + /* Give the callback (if any) a chance to handle the extension + * if it contains unsupported policies */ + if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && + cb(p_ctx, crt, &extn_oid, is_critical, + start_ext_octet, end_ext_octet) == 0) { + break; + } + + if (is_critical) { + return ret; + } else + /* + * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we + * cannot interpret or enforce the policy. However, it is up to + * the user to choose how to enforce the policies, + * unless the extension is critical. + */ + if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { + return ret; + } + } + break; + + default: + /* + * If this is a non-critical extension, which the oid layer + * supports, but there isn't an x509 parser for it, + * skip the extension. + */ + if (is_critical) { + return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } else { + *p = end_ext_octet; + } + } + } + + if (*p != end) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); + memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); + memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); + + /* + * Check for valid input + */ + if (crt == NULL || buf == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + /* Use the original buffer until we figure out actual length. */ + p = (unsigned char *) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERR_X509_INVALID_FORMAT; + } + + end = crt_end = p + len; + crt->raw.len = crt_end - buf; + if (make_copy != 0) { + /* Create and populate a new buffer for the raw field. */ + crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); + if (crt->raw.p == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } + + memcpy(crt->raw.p, buf, crt->raw.len); + crt->own_buffer = 1; + + p += crt->raw.len - len; + end = crt_end = p + len; + } else { + crt->raw.p = (unsigned char *) buf; + crt->own_buffer = 0; + } + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if ((ret = x509_get_version(&p, end, &crt->version)) != 0 || + (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 || + (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid, + &sig_params1)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + if (crt->version < 0 || crt->version > 2) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERR_X509_UNKNOWN_VERSION; + } + + crt->version++; + + if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); + } + + if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if ((ret = x509_get_dates(&p, end, &crt->valid_from, + &crt->valid_to)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if ((ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); + } + + if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + crt->pk_raw.p = p; + if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + crt->pk_raw.len = p - crt->pk_raw.p; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if (crt->version == 2 || crt->version == 3) { + ret = x509_get_uid(&p, end, &crt->issuer_id, 1); + if (ret != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + } + + if (crt->version == 2 || crt->version == 3) { + ret = x509_get_uid(&p, end, &crt->subject_id, 2); + if (ret != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + } + + if (crt->version == 3) { + ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); + if (ret != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + } + + if (p != end) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + if (crt->sig_oid.len != sig_oid2.len || + memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 || + sig_params1.tag != sig_params2.tag || + sig_params1.len != sig_params2.len || + (sig_params1.len != 0 && + memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERR_X509_SIG_MISMATCH; + } + + if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) { + mbedtls_x509_crt_free(crt); + return ret; + } + + if (p != end) { + mbedtls_x509_crt_free(crt); + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); + } + + return 0; +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if (crt == NULL || buf == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + while (crt->version != 0 && crt->next != NULL) { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if (crt->version != 0 && crt->next == NULL) { + crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); + + if (crt->next == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } + + prev = crt; + mbedtls_x509_crt_init(crt->next); + crt = crt->next; + } + + ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx); + if (ret != 0) { + if (prev) { + prev->next = NULL; + } + + if (crt != chain) { + mbedtls_free(crt); + } + + return ret; + } + + return 0; +} + +int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen) +{ + return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL); +} + +int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx) +{ + return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx); +} + +int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen) +{ + return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if (chain == NULL || buf == NULL) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if (buflen != 0 && buf[buflen - 1] == '\0' && + strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if (buf_format == MBEDTLS_X509_FORMAT_DER) { + return mbedtls_x509_crt_parse_der(chain, buf, buflen); + } +#else + return mbedtls_x509_crt_parse_der(chain, buf, buflen); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if (buf_format == MBEDTLS_X509_FORMAT_PEM) { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while (buflen > 1) { + size_t use_len; + mbedtls_pem_init(&pem); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer(&pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len); + + if (ret == 0) { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) { + return ret; + } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { + mbedtls_pem_free(&pem); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if (first_error == 0) { + first_error = ret; + } + + total_failed++; + continue; + } else { + break; + } + + ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen); + + mbedtls_pem_free(&pem); + + if (ret != 0) { + /* + * Quit parsing on a memory error + */ + if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) { + return ret; + } + + if (first_error == 0) { + first_error = ret; + } + + total_failed++; + continue; + } + + success = 1; + } + } + + if (success) { + return total_failed; + } else if (first_error) { + return first_error; + } else { + return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT; + } +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { + return ret; + } + + ret = mbedtls_x509_crt_parse(chain, buf, n); + + mbedtls_zeroize_and_free(buf, n); + + return ret; +} + +#if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) +int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen(path); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if (len > MAX_PATH - 3) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + memset(szDir, 0, sizeof(szDir)); + memset(filename, 0, MAX_PATH); + memcpy(filename, path, len); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + /* + * Note this function uses the code page CP_ACP which is the system default + * ANSI codepage. The input string is always described in BYTES and the + * output length is described in WCHARs. + */ + w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir, + MAX_PATH - 3); + if (w_ret == 0) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + hFind = FindFirstFileW(szDir, &file_data); + if (hFind == INVALID_HANDLE_VALUE) { + return MBEDTLS_ERR_X509_FILE_IO_ERROR; + } + + len = MAX_PATH - len; + do { + memset(p, 0, len); + + if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + continue; + } + w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, + -1, p, (int) len, NULL, NULL); + if (w_ret == 0) { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file(chain, filename); + if (w_ret < 0) { + ret++; + } else { + ret += w_ret; + } + } while (FindNextFileW(hFind, &file_data) != 0); + + if (GetLastError() != ERROR_NO_MORE_FILES) { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + } + +cleanup: + FindClose(hFind); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir(path); + + if (dir == NULL) { + return MBEDTLS_ERR_X509_FILE_IO_ERROR; + } + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) { + closedir(dir); + return ret; + } +#endif /* MBEDTLS_THREADING_C */ + + memset(&sb, 0, sizeof(sb)); + + while ((entry = readdir(dir)) != NULL) { + snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name), + "%s/%s", path, entry->d_name); + + if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } else if (stat(entry_name, &sb) == -1) { + if (errno == ENOENT) { + /* Broken symbolic link - ignore this entry. + stat(2) will return this error for either (a) a dangling + symlink or (b) a missing file. + Given that we have just obtained the filename from readdir, + assume that it does exist and therefore treat this as a + dangling symlink. */ + continue; + } else { + /* Some other file error; report the error. */ + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + } + + if (!S_ISREG(sb.st_mode)) { + continue; + } + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file(chain, entry_name); + if (t_ret < 0) { + ret++; + } else { + ret += t_ret; + } + } + +cleanup: + closedir(dir); + +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return ret; +} +#endif /* #if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) */ +#endif /* MBEDTLS_FS_IO */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define PRINT_ITEM(i) \ + do { \ + ret = mbedtls_snprintf(p, n, "%s" i, sep); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } while (0) + +#define CERT_TYPE(type, name) \ + do { \ + if (ns_cert_type & (type)) { \ + PRINT_ITEM(name); \ + } \ + } while (0) + +#define KEY_USAGE(code, name) \ + do { \ + if (key_usage & (code)) { \ + PRINT_ITEM(name); \ + } \ + } while (0) + +static int x509_info_ext_key_usage(char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while (cur != NULL) { + if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) { + desc = "???"; + } + + ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return 0; +} + +static int x509_info_cert_policies(char **buf, size_t *size, + const mbedtls_x509_sequence *certificate_policies) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = certificate_policies; + const char *sep = ""; + + while (cur != NULL) { + if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) { + desc = "???"; + } + + ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return 0; +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if (NULL == crt) { + ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n"); + MBEDTLS_X509_SAFE_SNPRINTF; + + return (int) (size - n); + } + + ret = mbedtls_snprintf(p, n, "%scert. version : %d\n", + prefix, crt->version); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf(p, n, "%sserial number : ", + prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets(p, n, &crt->serial); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets(p, n, &crt->issuer); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets(p, n, &crt->subject); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf(p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf(p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, + mbedtls_pk_get_name(&crt->pk))) != 0) { + return ret; + } + + ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen(&crt->pk)); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) { + ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false"); + MBEDTLS_X509_SAFE_SNPRINTF; + + if (crt->max_pathlen > 0) { + ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { + ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, + &crt->subject_alt_names, + prefix)) != 0) { + return ret; + } + } + + if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { + ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { + return ret; + } + } + + if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { + ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { + return ret; + } + } + + if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) { + ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = x509_info_ext_key_usage(&p, &n, + &crt->ext_key_usage)) != 0) { + return ret; + } + } + + if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) { + ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + + if ((ret = x509_info_cert_policies(&p, &n, + &crt->certificate_policies)) != 0) { + return ret; + } + } + + ret = mbedtls_snprintf(p, n, "\n"); + MBEDTLS_X509_SAFE_SNPRINTF; + + return (int) (size - n); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + MBEDTLS_X509_CRT_ERROR_INFO_LIST + { 0, NULL } +}; +#undef X509_CRT_ERROR_INFO + +int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, + uint32_t flags) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) { + if ((flags & cur->code) == 0) { + continue; + } + + ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if (flags != 0) { + ret = mbedtls_snprintf(p, n, "%sUnknown reason " + "(this should not happen)\n", prefix); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return (int) (size - n); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, + unsigned int usage) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) { + return 0; + } + + usage_must = usage & ~may_mask; + + if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + usage_may = usage & may_mask; + + if (((crt->key_usage & may_mask) | usage_may) != usage_may) { + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; + } + + return 0; +} + +int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) { + return 0; + } + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if (cur_oid->len == usage_len && + memcmp(cur_oid->p, usage_oid, usage_len) == 0) { + return 0; + } + + if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) { + return 0; + } + } + + return MBEDTLS_ERR_X509_BAD_INPUT_DATA; +} + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while (cur != NULL && cur->serial.len != 0) { + if (crt->serial.len == cur->serial.len && + memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) { + return 1; + } + + cur = cur->next; + } + + return 0; +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile, + const mbedtls_x509_time *now) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t psa_algorithm; +#else + const mbedtls_md_info_t *md_info; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + size_t hash_length; + + if (ca == NULL) { + return flags; + } + + while (crl_list != NULL) { + if (crl_list->version == 0 || + x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ + if (mbedtls_x509_crt_check_key_usage(ca, + MBEDTLS_X509_KU_CRL_SIGN) != 0) { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + } + + if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md); + if (psa_hash_compute(psa_algorithm, + crl_list->tbs.p, + crl_list->tbs.len, + hash, + sizeof(hash), + &hash_length) != PSA_SUCCESS) { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#else + md_info = mbedtls_md_info_from_type(crl_list->sig_md); + hash_length = mbedtls_md_get_size(md_info); + if (mbedtls_md(md_info, + crl_list->tbs.p, + crl_list->tbs.len, + hash) != 0) { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if (x509_profile_check_key(profile, &ca->pk) != 0) { + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + + if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, hash_length, + crl_list->sig.p, crl_list->sig.len) != 0) { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + +#if defined(MBEDTLS_HAVE_TIME_DATE) + /* + * Check for validity of CRL (Do not drop out) + */ + if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) { + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + } + + if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) { + flags |= MBEDTLS_X509_BADCRL_FUTURE; + } +#else + ((void) now); +#endif + + /* + * Check if certificate is revoked + */ + if (mbedtls_x509_crt_is_revoked(crt, crl_list)) { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return flags; +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature(const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx) +{ + size_t hash_len; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type(child->sig_md); + hash_len = mbedtls_md_get_size(md_info); + + /* Note: hash errors can happen only after an internal error */ + if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) { + return -1; + } +#else + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_hash_compute(hash_alg, + child->tbs.p, + child->tbs.len, + hash, + sizeof(hash), + &hash_len); + if (status != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* Skip expensive computation on obvious mismatch */ + if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) { + return -1; + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) { + return mbedtls_pk_verify_restartable(&parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len, &rs_ctx->pk); + } +#else + (void) rs_ctx; +#endif + + return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent(const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if (x509_name_cmp(&child->issuer, &parent->subject) != 0) { + return -1; + } + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if (top && parent->version < 3) { + need_ca_bit = 0; + } + + if (need_ca_bit && !parent->ca_istrue) { + return -1; + } + + if (need_ca_bit && + mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { + return -1; + } + + return 0; +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx, + const mbedtls_x509_time *now) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good = 0, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if (rs_ctx != NULL && rs_ctx->parent != NULL) { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for (parent = candidates; parent != NULL; parent = parent->next) { + /* basic parenting skills (name, CA bit, key usage) */ + if (x509_crt_check_parent(child, parent, top) != 0) { + continue; + } + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if (parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) { + continue; + } + + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature(child, parent, rs_ctx); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return ret; + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if (top && !signature_is_good) { + continue; + } + +#if defined(MBEDTLS_HAVE_TIME_DATE) + /* optional time check */ + if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */ + mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */ + if (fallback_parent == NULL) { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + + continue; + } +#else + ((void) now); +#endif + + *r_parent = parent; + *r_signature_is_good = signature_is_good; + + break; + } + + if (parent == NULL) { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } + + return 0; +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx, + const mbedtls_x509_time *now) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while (1) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in(child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx, now); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return ret; + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if (*parent != NULL || *parent_is_trusted == 0) { + break; + } + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if (*parent == NULL) { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return 0; +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) { + return -1; + } + + /* look for an exact match with trusted cert */ + for (cur = trust_ca; cur != NULL; cur = cur->next) { + if (crt->raw.len == cur->raw.len && + memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) { + return 0; + } + } + + /* too bad */ + return -1; +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermediate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + mbedtls_x509_crt *cur_trust_ca = NULL; + mbedtls_x509_time now; + +#if defined(MBEDTLS_HAVE_TIME_DATE) + if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) { + return MBEDTLS_ERR_X509_FATAL_ERROR; + } +#endif + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while (1) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + +#if defined(MBEDTLS_HAVE_TIME_DATE) + /* Check time-validity (all certificates) */ + if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) { + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + } + + if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) { + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + } +#endif + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if (child_is_trusted) { + return 0; + } + + /* Check signature algorithm: MD & PK algs */ + if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + } + + if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + } + + /* Special case: EE certs that are locally trusted */ + if (ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) { + return 0; + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + + /* Obtain list of potential trusted signers from CA callback, + * or use statically provided list. */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if (f_ca_cb != NULL) { + mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result); + mbedtls_free(ver_chain->trust_ca_cb_result); + ver_chain->trust_ca_cb_result = NULL; + + ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result); + if (ret != 0) { + return MBEDTLS_ERR_X509_FATAL_ERROR; + } + + cur_trust_ca = ver_chain->trust_ca_cb_result; + } else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + ((void) f_ca_cb); + ((void) p_ca_cb); + cur_trust_ca = trust_ca; + } + + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent(child, cur_trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx, + &now); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return ret; + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if (parent == NULL) { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return 0; + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if (ver_chain->len != 1 && + x509_name_cmp(&child->issuer, &child->subject) == 0) { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if (!parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) { + /* return immediately to avoid overflow the chain array */ + return MBEDTLS_ERR_X509_FATAL_ERROR; + } + + /* signature was checked while searching parent */ + if (!signature_is_good) { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + + /* check size of signing key */ + if (x509_profile_check_key(profile, &parent->pk) != 0) { + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +#ifdef _WIN32 +#ifdef _MSC_VER +#pragma comment(lib, "ws2_32.lib") +#include +#include +#elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600 +#include +#include +#else +/* inet_pton() is not supported, fallback to software version */ +#define MBEDTLS_TEST_SW_INET_PTON +#endif +#elif defined(__sun) +/* Solaris requires -lsocket -lnsl for inet_pton() */ +#elif defined(__has_include) +#if __has_include() +#include +#endif +#if __has_include() +#include +#endif +#endif + +/* Use whether or not AF_INET6 is defined to indicate whether or not to use + * the platform inet_pton() or a local implementation (below). The local + * implementation may be used even in cases where the platform provides + * inet_pton(), e.g. when there are different includes required and/or the + * platform implementation requires dependencies on additional libraries. + * Specifically, Windows requires custom includes and additional link + * dependencies, and Solaris requires additional link dependencies. + * Also, as a coarse heuristic, use the local implementation if the compiler + * does not support __has_include(), or if the definition of AF_INET6 is not + * provided by headers included (or not) via __has_include() above. + * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names + * despite having a platform that has inet_pton. */ +#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names +/* Definition located further below to possibly reduce compiler inlining */ +static int x509_inet_pton_ipv4(const char *src, void *dst); + +#define li_cton(c, n) \ + (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) + +static int x509_inet_pton_ipv6(const char *src, void *dst) +{ + const unsigned char *p = (const unsigned char *) src; + int nonzero_groups = 0, num_digits, zero_group_start = -1; + uint16_t addr[8]; + do { + /* note: allows excess leading 0's, e.g. 1:0002:3:... */ + uint16_t group = num_digits = 0; + for (uint8_t digit; num_digits < 4; num_digits++) { + if (li_cton(*p, digit) == 0) { + break; + } + group = (group << 4) | digit; + p++; + } + if (num_digits != 0) { + MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); + nonzero_groups++; + if (*p == '\0') { + break; + } else if (*p == '.') { + /* Don't accept IPv4 too early or late */ + if ((nonzero_groups == 0 && zero_group_start == -1) || + nonzero_groups >= 7) { + break; + } + + /* Walk back to prior ':', then parse as IPv4-mapped */ + int steps = 4; + do { + p--; + steps--; + } while (*p != ':' && steps > 0); + + if (*p != ':') { + break; + } + p++; + nonzero_groups--; + if (x509_inet_pton_ipv4((const char *) p, + addr + nonzero_groups) != 0) { + break; + } + + nonzero_groups += 2; + p = (const unsigned char *) ""; + break; + } else if (*p != ':') { + return -1; + } + } else { + /* Don't accept a second zero group or an invalid delimiter */ + if (zero_group_start != -1 || *p != ':') { + return -1; + } + zero_group_start = nonzero_groups; + + /* Accept a zero group at start, but it has to be a double colon */ + if (zero_group_start == 0 && *++p != ':') { + return -1; + } + + if (p[1] == '\0') { + ++p; + break; + } + } + ++p; + } while (nonzero_groups < 8); + + if (*p != '\0') { + return -1; + } + + if (zero_group_start != -1) { + if (nonzero_groups > 6) { + return -1; + } + int zero_groups = 8 - nonzero_groups; + int groups_after_zero = nonzero_groups - zero_group_start; + + /* Move the non-zero part to after the zeroes */ + if (groups_after_zero) { + memmove(addr + zero_group_start + zero_groups, + addr + zero_group_start, + groups_after_zero * sizeof(*addr)); + } + memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); + } else { + if (nonzero_groups != 8) { + return -1; + } + } + memcpy(dst, addr, sizeof(addr)); + return 0; +} + +static int x509_inet_pton_ipv4(const char *src, void *dst) +{ + const unsigned char *p = (const unsigned char *) src; + uint8_t *res = (uint8_t *) dst; + uint8_t digit, num_digits = 0; + uint8_t num_octets = 0; + uint16_t octet; + + do { + octet = num_digits = 0; + do { + digit = *p - '0'; + if (digit > 9) { + break; + } + + /* Don't allow leading zeroes. These might mean octal format, + * which this implementation does not support. */ + if (octet == 0 && num_digits > 0) { + return -1; + } + + octet = octet * 10 + digit; + num_digits++; + p++; + } while (num_digits < 3); + + if (octet >= 256 || num_digits > 3 || num_digits == 0) { + return -1; + } + *res++ = (uint8_t) octet; + num_octets++; + } while (num_octets < 4 && *p++ == '.'); + return num_octets == 4 && *p == '\0' ? 0 : -1; +} + +#else + +static int x509_inet_pton_ipv6(const char *src, void *dst) +{ + return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; +} + +static int x509_inet_pton_ipv4(const char *src, void *dst) +{ + return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; +} + +#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names + +size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) +{ + return strchr(cn, ':') == NULL + ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 + : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn(const mbedtls_x509_buf *name, + const char *cn, size_t cn_len) +{ + /* try exact match */ + if (name->len == cn_len && + x509_memcasecmp(cn, name->p, cn_len) == 0) { + return 0; + } + + /* try wildcard match */ + if (x509_check_wildcard(cn, name) == 0) { + return 0; + } + + return -1; +} + +static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, + const char *cn, size_t cn_len) +{ + uint32_t ip[4]; + cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); + if (cn_len == 0) { + return -1; + } + + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + const unsigned char san_type = (unsigned char) cur->buf.tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && + cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { + return 0; + } + } + + return -1; +} + +static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, + const char *cn, size_t cn_len) +{ + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + const unsigned char san_type = (unsigned char) cur->buf.tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && + cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { + return 0; + } + } + + return -1; +} + +/* + * Check for SAN match, see RFC 5280 Section 4.2.1.6 + */ +static int x509_crt_check_san(const mbedtls_x509_sequence *san, + const char *cn, size_t cn_len) +{ + int san_ip = 0; + int san_uri = 0; + /* Prioritize DNS name over other subtypes due to popularity */ + for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { + switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { + case MBEDTLS_X509_SAN_DNS_NAME: + if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { + return 0; + } + break; + case MBEDTLS_X509_SAN_IP_ADDRESS: + san_ip = 1; + break; + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: + san_uri = 1; + break; + /* (We may handle other types here later.) */ + default: /* Unrecognized type */ + break; + } + } + if (san_ip) { + if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { + return 0; + } + } + if (san_uri) { + if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { + return 0; + } + } + + return -1; +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name(const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags) +{ + const mbedtls_x509_name *name; + size_t cn_len = strlen(cn); + + if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { + if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) { + return; + } + } else { + for (name = &crt->subject; name != NULL; name = name->next) { + if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && + x509_crt_check_cn(&name->val, cn, cn_len) == 0) { + return; + } + } + + } + + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for (i = ver_chain->len; i != 0; --i) { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if (NULL != f_vrfy) { + if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) { + return ret; + } + } + + *flags |= cur_flags; + } + + return 0; +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + * + * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` + * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the + * verification routine to search for trusted signers, and CRLs will + * be disabled. Otherwise, `trust_ca` will be used as the static list + * of trusted signers, and `ca_crl` will be use as the static list + * of CRLs. + */ +static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, + mbedtls_x509_crt *, + int, + uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; + + *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset(&ver_chain); + + if (profile == NULL) { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if (cn != NULL) { + x509_crt_verify_name(crt, cn, &ee_flags); + } + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type(&crt->pk); + + if (x509_profile_check_pk_alg(profile, pk_type) != 0) { + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + } + + if (x509_profile_check_key(profile, &crt->pk) != 0) { + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + } + + /* Check the chain */ + ret = x509_crt_verify_chain(crt, trust_ca, ca_crl, + f_ca_cb, p_ca_cb, profile, + &ver_chain, rs_ctx); + + if (ret != 0) { + goto exit; + } + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy); + +exit: + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result); + mbedtls_free(ver_chain.trust_ca_cb_result); + ver_chain.trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { + mbedtls_x509_crt_restart_free(rs_ctx); + } +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + } + + if (ret != 0) { + *flags = (uint32_t) -1; + return ret; + } + + if (*flags != 0) { + return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; + } + + return 0; +} + + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, + NULL, NULL, + &mbedtls_x509_crt_profile_default, + cn, flags, + f_vrfy, p_vrfy, NULL); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, NULL); +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/* + * Verify the certificate validity (user-chosen profile, CA callback, + * not restartable). + */ +int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy) +{ + return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL, + f_ca_cb, p_ca_cb, + profile, cn, flags, + f_vrfy, p_vrfy, NULL); +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx) +{ + return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, rs_ctx); +} + + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) +{ + memset(crt, 0, sizeof(mbedtls_x509_crt)); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + + while (cert_cur != NULL) { + mbedtls_pk_free(&cert_cur->pk); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free(cert_cur->sig_opts); +#endif + + mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); + mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); + mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); + mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); + mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); + mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next); + + if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { + mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len); + } + + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt)); + if (cert_prv != crt) { + mbedtls_free(cert_prv); + } + } +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx) +{ + mbedtls_pk_restart_init(&ctx->pk); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset(&ctx->ver_chain); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) +{ + if (ctx == NULL) { + return; + } + + mbedtls_pk_restart_free(&ctx->pk); + mbedtls_x509_crt_restart_init(ctx); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/x509write_csr.c b/matter/mbedtls/tinycrypt/src/x509write_csr.c new file mode 100644 index 0000000000..d996052ba0 --- /dev/null +++ b/matter/mbedtls/tinycrypt/src/x509write_csr.c @@ -0,0 +1,343 @@ +/* + * X.509 Certificate Signing Request writing + * + * 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. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/x509_csr.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "psa_util_internal.h" +#include "md_psa.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#include "mbedtls/platform.h" + +void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_x509write_csr)); +} + +void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) +{ + mbedtls_asn1_free_named_data_list(&ctx->subject); + mbedtls_asn1_free_named_data_list(&ctx->extensions); + + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); +} + +void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, + const char *subject_name) +{ + return mbedtls_x509_string_to_names(&ctx->subject, subject_name); +} + +int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len) +{ + return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, + critical, val, val_len); +} + +int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, + const mbedtls_x509_san_list *san_list) +{ + return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); +} + +int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) +{ + unsigned char buf[4] = { 0 }; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); + if (ret < 3 || ret > 4) { + return ret; + } + + ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), + 0, c, (size_t) ret); + if (ret != 0) { + return ret; + } + + return 0; +} + +int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type) +{ + unsigned char buf[4] = { 0 }; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); + if (ret < 3 || ret > 4) { + return ret; + } + + ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), + 0, c, (size_t) ret); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, size_t sig_size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_len; + psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, + ctx->extensions)); + + if (len) { + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); + + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + } + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); + + MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, + buf, c - buf)); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, + ctx->subject)); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + /* + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if (psa_hash_compute(hash_alg, + c, + len, + hash, + sizeof(hash), + &hash_len) != PSA_SUCCESS) { + return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + } +#else /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); + if (ret != 0) { + return ret; + } +#endif + if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, + sig, sig_size, &sig_len, + f_rng, p_rng)) != 0) { + return ret; + } + + if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { + pk_alg = MBEDTLS_PK_RSA; + } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { + pk_alg = MBEDTLS_PK_ECDSA; + } else { + return MBEDTLS_ERR_X509_INVALID_ALG; + } + + if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len)) != 0) { + return ret; + } + + /* + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. + */ + memmove(buf, c, len); + + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, + mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len, pk_alg)); + + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ + c2 -= len; + memmove(c2, buf, len); + + /* ASN encode the total size and tag the CSR data with it. */ + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); + MBEDTLS_ASN1_CHK_ADD(len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + /* Zero the unused bytes at the start of buf */ + memset(buf, 0, c2 - buf); + + return (int) len; +} + +int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret; + unsigned char *sig; + + if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { + return MBEDTLS_ERR_X509_ALLOC_FAILED; + } + + ret = x509write_csr_der_internal(ctx, buf, size, + sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, + f_rng, p_rng); + + mbedtls_free(sig); + + return ret; +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen = 0; + + if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, + f_rng, p_rng)) < 0) { + return ret; + } + + if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, + buf + size - ret, + ret, buf, size, &olen)) != 0) { + return ret; + } + + return 0; +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ From 7196420e371ad1a5920000dee300bb0d701497de Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Wed, 20 Nov 2024 19:28:27 +0530 Subject: [PATCH 06/11] WIP: add missing platform functions --- matter/mbedtls/tinycrypt/inc/mbedtls/oid.h | 734 ---- matter/mbedtls/tinycrypt/inc/mbedtls/pk.h | 1107 ------ .../tinycrypt/inc/tinycrypt/tinycrypt_util.h | 2 + matter/mbedtls/tinycrypt/src/ecc.c | 2344 +++++++----- matter/mbedtls/tinycrypt/src/ecc_dh.c | 201 +- matter/mbedtls/tinycrypt/src/ecc_dsa.c | 427 ++- matter/mbedtls/tinycrypt/src/oid.c | 1166 ------ matter/mbedtls/tinycrypt/src/pk.c | 982 ----- matter/mbedtls/tinycrypt/src/pk_wrap.c | 1850 --------- matter/mbedtls/tinycrypt/src/pk_wrap.h | 168 - matter/mbedtls/tinycrypt/src/pkparse.c | 1857 --------- matter/mbedtls/tinycrypt/src/pkwrite.c | 848 ----- matter/mbedtls/tinycrypt/src/tinycrypt_util.c | 51 + matter/mbedtls/tinycrypt/src/utils.c | 74 - matter/mbedtls/tinycrypt/src/x509_crt.c | 3308 ----------------- matter/mbedtls/tinycrypt/src/x509write_csr.c | 343 -- 16 files changed, 1736 insertions(+), 13726 deletions(-) delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/oid.h delete mode 100644 matter/mbedtls/tinycrypt/inc/mbedtls/pk.h delete mode 100644 matter/mbedtls/tinycrypt/src/oid.c delete mode 100644 matter/mbedtls/tinycrypt/src/pk.c delete mode 100644 matter/mbedtls/tinycrypt/src/pk_wrap.c delete mode 100644 matter/mbedtls/tinycrypt/src/pk_wrap.h delete mode 100644 matter/mbedtls/tinycrypt/src/pkparse.c delete mode 100644 matter/mbedtls/tinycrypt/src/pkwrite.c delete mode 100644 matter/mbedtls/tinycrypt/src/utils.c delete mode 100644 matter/mbedtls/tinycrypt/src/x509_crt.c delete mode 100644 matter/mbedtls/tinycrypt/src/x509write_csr.c diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h b/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h deleted file mode 100644 index 9545072296..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/oid.h +++ /dev/null @@ -1,734 +0,0 @@ -/** - * \file oid.h - * - * \brief Object Identifier (OID) database - */ -/* - * 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. - */ -#ifndef MBEDTLS_OID_H -#define MBEDTLS_OID_H -#include "mbedtls/private_access.h" - -#include "mbedtls/build_info.h" - -#include "mbedtls/asn1.h" -#include "mbedtls/pk.h" - -#include - -#if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher.h" -#endif - -#include "mbedtls/md.h" - -/** OID is not found. */ -#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E -/** output buffer is too small */ -#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B - -/* This is for the benefit of X.509, but defined here in order to avoid - * having a "backwards" include of x.509.h here */ -/* - * X.509 extension types (internal, arbitrary values for bitsets) - */ -#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) -#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) -#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) -#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) -#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) -#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) -#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) -#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) -#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) -#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) -#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) -#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) -#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) -#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) -#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) -#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) - -/* - * Maximum number of OID components allowed - */ -#define MBEDTLS_OID_MAX_COMPONENTS 128 - -/* - * Top level OID tuples - */ -#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ -#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ -#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ -#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ - -/* - * ISO Member bodies OID parts - */ -#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ -#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ -#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ -#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ -#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_ANSI_X9_62 - -/* - * ISO Identified organization OID parts - */ -#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ -#define MBEDTLS_OID_ORG_OIW "\x0e" -#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" -#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" -#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" -#define MBEDTLS_OID_ORG_THAWTE "\x65" /* thawte(101) */ -#define MBEDTLS_OID_THAWTE MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_ORG_THAWTE -#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ -#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_ORG_CERTICOM -#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ -#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_ORG_TELETRUST - -/* - * ISO ITU OID parts - */ -#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ -#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ - -#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ -#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ - -#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ -#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ - -/* ISO arc for standard certificate and CRL extensions */ -#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ - -#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ - -/** - * Private Internet Extensions - * { iso(1) identified-organization(3) dod(6) internet(1) - * security(5) mechanisms(5) pkix(7) } - */ -#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD \ - "\x01" -#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" - -/* - * Arc for standard naming attributes - */ -#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ -#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ -#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ -#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ -#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ -#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ -#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ -#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ -#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ -#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ -#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ -#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ -#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ -#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ -#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ -#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */ -#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ -#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ - -#define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ -#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ - -/* - * OIDs for standard certificate extensions - */ -#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ -#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ -#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ -#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ -#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ -#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ -#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ -#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ -#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ -#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ -#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ -#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ -#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ -#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ -#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - -/* - * Certificate policies - */ -#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ - -/* - * Netscape certificate extensions - */ -#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" -#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" -#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" -#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" -#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" -#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" -#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" -#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" -#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" -#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" -#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" - -/* - * OIDs for CRL extensions - */ -#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" -#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - -/* - * X.509 v3 Extended key usage OIDs - */ -#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ - -#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ -#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ -#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ -#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ -#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ -#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ -#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - -/** - * Wi-SUN Alliance Field Area Network - * { iso(1) identified-organization(3) dod(6) internet(1) - * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } - */ -#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" - -#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ -#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ - -/* - * PKCS definition OIDs - */ - -#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ -#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ -#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ -#define MBEDTLS_OID_PKCS7 MBEDTLS_OID_PKCS "\x07" /**< pkcs-7 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 } */ -#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ -#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ - -/* - * PKCS#1 OIDs - */ -#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ -#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ -#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ -#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ -#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ -#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ -#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ - -#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - -#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ - -/* RFC 4055 */ -#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ -#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ - -/* - * Digest algorithms - */ -#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ - -#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */ - - -#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ - -#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ - -#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ - -#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ - -#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ - -#define MBEDTLS_OID_HMAC_SHA3_224 MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */ - -#define MBEDTLS_OID_HMAC_SHA3_256 MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */ - -#define MBEDTLS_OID_HMAC_SHA3_384 MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */ - -#define MBEDTLS_OID_HMAC_SHA3_512 MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */ - -#define MBEDTLS_OID_HMAC_RIPEMD160 MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */ - -/* - * Encryption algorithms - */ -#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG \ - MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ -#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ -#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ - -/* - * Key Wrapping algorithms - */ -/* - * RFC 5649 - */ -#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ -#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ -#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ -#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ -#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ -#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ -/* - * PKCS#5 OIDs - */ -#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ -#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ -#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ - -/* - * PKCS#5 PBES1 algorithms - */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ - -/* - * PKCS#7 OIDs - */ -#define MBEDTLS_OID_PKCS7_DATA MBEDTLS_OID_PKCS7 "\x01" /**< Content type is Data OBJECT IDENTIFIER ::= {pkcs-7 1} */ -#define MBEDTLS_OID_PKCS7_SIGNED_DATA MBEDTLS_OID_PKCS7 "\x02" /**< Content type is Signed Data OBJECT IDENTIFIER ::= {pkcs-7 2} */ -#define MBEDTLS_OID_PKCS7_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x03" /**< Content type is Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 3} */ -#define MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA MBEDTLS_OID_PKCS7 "\x04" /**< Content type is Signed and Enveloped Data OBJECT IDENTIFIER ::= {pkcs-7 4} */ -#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05" /**< Content type is Digested Data OBJECT IDENTIFIER ::= {pkcs-7 5} */ -#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06" /**< Content type is Encrypted Data OBJECT IDENTIFIER ::= {pkcs-7 6} */ - -/* - * PKCS#8 OIDs - */ -#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ - -/* - * PKCS#12 PBE OIDs - */ -#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ - -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ - -/* - * EC key algorithms from RFC 5480 - */ - -/* id-ecPublicKey OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ -#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" - -/* id-ecDH OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) - * schemes(1) ecdh(12) } */ -#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" - -/* - * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 - */ - -/* secp192r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ -#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" - -/* secp224r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ -#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" - -/* secp256r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ -#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" - -/* secp384r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ -#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" - -/* secp521r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ -#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" - -/* secp192k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ -#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" - -/* secp224k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ -#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" - -/* secp256k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ -#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" - -/* RFC 5639 4.1 - * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) - * identified-organization(3) teletrust(36) algorithm(3) signature- - * algorithm(3) ecSign(2) 8} - * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} - * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ -#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" - -/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ -#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" - -/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ -#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" - -/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ -#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" - -/* - * SEC1 C.1 - * - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} - */ -#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" -#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" - -/* - * ECDSA signature identifiers, from RFC 5480 - */ -#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ -#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ - -/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" - -/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" - -/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 2 } */ -#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" - -/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 3 } */ -#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" - -/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 4 } */ -#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" - -/* - * EC key algorithms from RFC 8410 - */ - -#define MBEDTLS_OID_X25519 MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } */ -#define MBEDTLS_OID_X448 MBEDTLS_OID_THAWTE "\x6f" /**< id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } */ -#define MBEDTLS_OID_ED25519 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } */ -#define MBEDTLS_OID_ED448 MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Base OID descriptor structure - */ -typedef struct mbedtls_oid_descriptor_t { - const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ - size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ -#if !defined(MBEDTLS_X509_REMOVE_INFO) - const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ - const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ -#endif -} mbedtls_oid_descriptor_t; - -/** - * \brief Translate an ASN.1 OID into its numeric representation - * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") - * - * \param buf buffer to put representation in - * \param size size of the buffer - * \param oid OID to translate - * - * \return Length of the string written (excluding final NULL) or - * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error - */ -int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); - -/** - * \brief Translate a string containing a dotted-decimal - * representation of an ASN.1 OID into its encoded form - * (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D"). - * On success, this function allocates oid->buf from the - * heap. It must be freed by the caller using mbedtls_free(). - * - * \param oid #mbedtls_asn1_buf to populate with the DER-encoded OID - * \param oid_str string representation of the OID to parse - * \param size length of the OID string, not including any null terminator - * - * \return 0 if successful - * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not - * represent a valid OID - * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to - * allocate oid->buf - */ -int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size); - -/** - * \brief Translate an X.509 extension OID into local values - * - * \param oid OID to use - * \param ext_type place to store the extension type - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); - -/** - * \brief Translate an X.509 attribute type OID into the short name - * (e.g. the OID for an X520 Common Name into "CN") - * - * \param oid OID to use - * \param short_name place to store the string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); - -/** - * \brief Translate PublicKeyAlgorithm OID into pk_type - * - * \param oid OID to use - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); - -/** - * \brief Translate pk_type into PublicKeyAlgorithm OID - * - * \param pk_alg Public key type to look for - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, - const char **oid, size_t *olen); - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -/** - * \brief Translate NamedCurve OID into an EC group identifier - * - * \param oid OID to use - * \param grp_id place to store group id - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); - -/** - * \brief Translate EC group identifier into NamedCurve OID - * - * \param grp_id EC group identifier - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, - const char **oid, size_t *olen); - -/** - * \brief Translate AlgorithmIdentifier OID into an EC group identifier, - * for curves that are directly encoded at this level - * - * \param oid OID to use - * \param grp_id place to store group id - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); - -/** - * \brief Translate EC group identifier into AlgorithmIdentifier OID, - * for curves that are directly encoded at this level - * - * \param grp_id EC group identifier - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id, - const char **oid, size_t *olen); -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -/** - * \brief Translate SignatureAlgorithm OID into md_type and pk_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); - -/** - * \brief Translate SignatureAlgorithm OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); - -/** - * \brief Translate md_type and pk_type into SignatureAlgorithm OID - * - * \param md_alg message digest algorithm - * \param pk_alg public key algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const char **oid, size_t *olen); - -/** - * \brief Translate hmac algorithm OID into md_type - * - * \param oid OID to use - * \param md_hmac place to store message hmac algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); - -/** - * \brief Translate hash algorithm OID into md_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); - -#if !defined(MBEDTLS_X509_REMOVE_INFO) -/** - * \brief Translate Extended Key Usage OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); -#endif - -/** - * \brief Translate certificate policies OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_certificate_policies(const mbedtls_asn1_buf *oid, const char **desc); - -/** - * \brief Translate md_type into hash algorithm OID - * - * \param md_alg message digest algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); - -#if defined(MBEDTLS_CIPHER_C) -/** - * \brief Translate encryption algorithm OID into cipher_type - * - * \param oid OID to use - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_PKCS12_C) -/** - * \brief Translate PKCS#12 PBE algorithm OID into md_type and - * cipher_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, - mbedtls_cipher_type_t *cipher_alg); -#endif /* MBEDTLS_PKCS12_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* oid.h */ diff --git a/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h b/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h deleted file mode 100644 index 68ebd73885..0000000000 --- a/matter/mbedtls/tinycrypt/inc/mbedtls/pk.h +++ /dev/null @@ -1,1107 +0,0 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer - */ -/* - * 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. - */ - -#ifndef MBEDTLS_PK_H -#define MBEDTLS_PK_H -#include "mbedtls/private_access.h" - -#include "mbedtls/build_info.h" - -#include "mbedtls/md.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_PSA_CRYPTO_C) -#include "psa/crypto.h" -#endif - -/** Memory allocation failed. */ -#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 -/** Type mismatch, eg attempt to encrypt with an ECDSA key */ -#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 -/** Bad input parameters to function. */ -#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 -/** Read/write of file failed. */ -#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 -/** Unsupported key version */ -#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 -/** Invalid key tag or value. */ -#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 -/** Key algorithm is unsupported (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 -/** Private key password can't be empty. */ -#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 -/** Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 -/** The pubkey tag or value is invalid (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 -/** The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 -/** Elliptic curve is unsupported (only NIST curves are supported). */ -#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 -/** Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 -/** The buffer contains a valid signature followed by more data. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 -/** The output buffer is too small. */ -#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Public key types - */ -typedef enum { - MBEDTLS_PK_NONE=0, - MBEDTLS_PK_RSA, - MBEDTLS_PK_ECKEY, - MBEDTLS_PK_ECKEY_DH, - MBEDTLS_PK_ECDSA, - MBEDTLS_PK_RSA_ALT, - MBEDTLS_PK_RSASSA_PSS, - MBEDTLS_PK_OPAQUE, -} mbedtls_pk_type_t; - -/** - * \brief Options for RSASSA-PSS signature verification. - * See \c mbedtls_rsa_rsassa_pss_verify_ext() - */ -typedef struct mbedtls_pk_rsassa_pss_options { - /** The digest to use for MGF1 in PSS. - * - * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled and #MBEDTLS_RSA_C is - * disabled, this must be equal to the \c md_alg argument passed - * to mbedtls_pk_verify_ext(). In a future version of the library, - * this constraint may apply whenever #MBEDTLS_USE_PSA_CRYPTO is - * enabled regardless of the status of #MBEDTLS_RSA_C. - */ - mbedtls_md_type_t mgf1_hash_id; - - /** The expected length of the salt, in bytes. This may be - * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. - * - * \note When #MBEDTLS_USE_PSA_CRYPTO is enabled, only - * #MBEDTLS_RSA_SALT_LEN_ANY is valid. Any other value may be - * ignored (allowing any salt length). - */ - int expected_salt_len; - -} mbedtls_pk_rsassa_pss_options; - -/** - * \brief Maximum size of a signature made by mbedtls_pk_sign(). - */ -/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature - * size among the supported signature types. Do it by starting at 0, - * then incrementally increasing to be large enough for each supported - * signature mechanism. - * - * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled - * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C - * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). - */ -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 - -#if (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT)) && \ - MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* For RSA, the signature can be as large as the bignum module allows. - * For RSA_ALT, the signature size is not necessarily tied to what the - * bignum module can do, but in the absence of any specific setting, - * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE -#endif - -#if defined(MBEDTLS_ECDSA_C) && \ - MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* For ECDSA, the ecdsa module exports a constant for the maximum - * signature size. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made - * through the PSA API in the PSA representation. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE -#endif - -#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE -/* The Mbed TLS representation is different for ECDSA signatures: - * PSA uses the raw concatenation of r and s, - * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). - * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the - * types, lengths (represented by up to 2 bytes), and potential leading - * zeros of the INTEGERs and the SEQUENCE. */ -#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE -#define MBEDTLS_PK_SIGNATURE_MAX_SIZE (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11) -#endif -#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ - -/* Internal helper to define which fields in the pk_context structure below - * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly) - * format. It should be noted that this only affects how data is stored, not - * which functions are used for various operations. The overall picture looks - * like this: - * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data - * structure and legacy functions - * - if USE_PSA is defined and - * - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly - * format and use PSA functions - * - if !ECP_C then use new raw data and PSA functions directly. - * - * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long - * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the - * ecp_keypair structure inside the pk_context so they can modify it using - * ECP functions which are not under PK module's control. - */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \ - !defined(MBEDTLS_ECP_C) -#define MBEDTLS_PK_USE_PSA_EC_DATA -#endif - -/* Helper symbol to state that the PK module has support for EC keys. This - * can either be provided through the legacy ECP solution or through the - * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA. */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_ECP_C) -#define MBEDTLS_PK_HAVE_ECC_KEYS -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */ - -/** - * \brief Types for interfacing with the debug module - */ -typedef enum { - MBEDTLS_PK_DEBUG_NONE = 0, - MBEDTLS_PK_DEBUG_MPI, - MBEDTLS_PK_DEBUG_ECP, - MBEDTLS_PK_DEBUG_PSA_EC, -} mbedtls_pk_debug_type; - -/** - * \brief Item to send to the debug module - */ -typedef struct mbedtls_pk_debug_item { - mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); - const char *MBEDTLS_PRIVATE(name); - void *MBEDTLS_PRIVATE(value); -} mbedtls_pk_debug_item; - -/** Maximum number of item send for debugging, plus 1 */ -#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 - -/** - * \brief Public key information and operations - * - * \note The library does not support custom pk info structures, - * only built-in structures returned by - * mbedtls_cipher_info_from_type(). - */ -typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - -#define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \ - PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) -/** - * \brief Public key container - */ -typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ - void *MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ - /* The following field is used to store the ID of a private key in the - * following cases: - * - opaque key when MBEDTLS_PSA_CRYPTO_C is defined - * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case: - * - the pk_ctx above is not not used to store the private key anymore. - * Actually that field not populated at all in this case because also - * the public key will be stored in raw format as explained below - * - this ID is used for all private key operations (ex: sign, check - * key pair, key write, etc) using PSA functions - * - * Note: this private key storing solution only affects EC keys, not the - * other ones. The latters still use the pk_ctx to store their own - * context. - * - * Note: this priv_id is guarded by MBEDTLS_PSA_CRYPTO_C and not by - * MBEDTLS_PK_USE_PSA_EC_DATA (as the public counterpart below) because, - * when working with opaque keys, it can be used also in - * mbedtls_pk_sign_ext for RSA keys. */ -#if defined(MBEDTLS_PSA_CRYPTO_C) - mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ -#else - uint32_t MBEDTLS_PRIVATE(priv_id); /**< Key ID for opaque keys */ -#endif /* MBEDTLS_PSA_CRYPTO_C */ - /* The following fields are meant for storing the public key in raw format - * which is handy for: - * - easily importing it into the PSA context - * - reducing the ECP module dependencies in the PK one. - * - * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled: - * - the pk_ctx above is not used anymore for storing the public key - * inside the ecp_keypair structure - * - the following fields are used for all public key operations: signature - * verify, key pair check and key write. - * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy - * ecp_keypair structure is used for storing the public key and performing - * all the operations. - * - * Note: This new public key storing solution only works for EC keys, not - * other ones. The latters still use pk_ctx to store their own - * context. - */ - uint8_t MBEDTLS_PRIVATE(pub_raw)[66 * 2 + 1]; /**< Raw public key */ - size_t MBEDTLS_PRIVATE(pub_raw_len); /**< Valid bytes in "pub_raw" */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - psa_ecc_family_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ -#else - uint8_t MBEDTLS_PRIVATE(ec_family); /**< EC family of pk */ -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - size_t MBEDTLS_PRIVATE(ec_bits); /**< Curve's bits of pk */ -} mbedtls_pk_context; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/** - * \brief Context for resuming operations - */ -typedef struct { - const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info); /**< Public key information */ - void *MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ -} mbedtls_pk_restart_ctx; -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ -/* Now we can declare functions that take a pointer to that */ -typedef void mbedtls_pk_restart_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Types for RSA-alt abstraction - */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len); -typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig); -typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Return information associated with the given PK type - * - * \param pk_type PK type to search for. - * - * \return The PK info associated with the type or NULL if not found. - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); - -/** - * \brief Initialize a #mbedtls_pk_context (as NONE). - * - * \param ctx The context to initialize. - * This must not be \c NULL. - */ -void mbedtls_pk_init(mbedtls_pk_context *ctx); - -/** - * \brief Free the components of a #mbedtls_pk_context. - * - * \param ctx The context to clear. It must have been initialized. - * If this is \c NULL, this function does nothing. - * - * \note For contexts that have been set up with - * mbedtls_pk_setup_opaque(), this does not free the underlying - * PSA key and you still need to call psa_destroy_key() - * independently if you want to destroy that key. - */ -void mbedtls_pk_free(mbedtls_pk_context *ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/** - * \brief Initialize a restart context - * - * \param ctx The context to initialize. - * This must not be \c NULL. - */ -void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx); - -/** - * \brief Free the components of a restart context - * - * \param ctx The context to clear. It must have been initialized. - * If this is \c NULL, this function does nothing. - */ -void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/** - * \brief Initialize a PK context with the information given - * and allocates the type-specific PK subcontext. - * - * \param ctx Context to initialize. It must not have been set - * up yet (type #MBEDTLS_PK_NONE). - * \param info Information to use - * - * \return 0 on success, - * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, - * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - * - * \note For contexts holding an RSA-alt key, use - * \c mbedtls_pk_setup_rsa_alt() instead. - */ -int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Initialize a PK context to wrap a PSA key. - * - * \note This function replaces mbedtls_pk_setup() for contexts - * that wrap a (possibly opaque) PSA key instead of - * storing and manipulating the key material directly. - * - * \param ctx The context to initialize. It must be empty (type NONE). - * \param key The PSA key to wrap, which must hold an ECC or RSA key - * pair (see notes below). - * - * \note The wrapped key must remain valid as long as the - * wrapping PK context is in use, that is at least between - * the point this function is called and the point - * mbedtls_pk_free() is called on this context. The wrapped - * key might then be independently used or destroyed. - * - * \note This function is currently only available for ECC or RSA - * key pairs (that is, keys containing private key material). - * Support for other key types may be added later. - * - * \return \c 0 on success. - * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input - * (context already used, invalid key identifier). - * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an - * ECC key pair. - * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - */ -int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, - const mbedtls_svc_key_id_t key); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Initialize an RSA-alt context - * - * \param ctx Context to initialize. It must not have been set - * up yet (type #MBEDTLS_PK_NONE). - * \param key RSA key pointer - * \param decrypt_func Decryption function - * \param sign_func Signing function - * \param key_len_func Function returning key length in bytes - * - * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the - * context wasn't already initialized as RSA_ALT. - * - * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. - */ -int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Get the size in bits of the underlying key - * - * \param ctx The context to query. It must have been initialized. - * - * \return Key size in bits, or 0 on error - */ -size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); - -/** - * \brief Get the length in bytes of the underlying key - * - * \param ctx The context to query. It must have been initialized. - * - * \return Key length in bytes, or 0 on error - */ -static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) -{ - return (mbedtls_pk_get_bitlen(ctx) + 7) / 8; -} - -/** - * \brief Tell if a context can do the operation given by type - * - * \param ctx The context to query. It must have been initialized. - * \param type The desired type. - * - * \return 1 if the context can do operations on the given type. - * \return 0 if the context cannot do the operations on the given - * type. This is always the case for a context that has - * been initialized but not set up, or that has been - * cleared with mbedtls_pk_free(). - */ -int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Tell if context can do the operation given by PSA algorithm - * - * \param ctx The context to query. It must have been initialized. - * \param alg PSA algorithm to check against, the following are allowed: - * PSA_ALG_RSA_PKCS1V15_SIGN(hash), - * PSA_ALG_RSA_PSS(hash), - * PSA_ALG_RSA_PKCS1V15_CRYPT, - * PSA_ALG_ECDSA(hash), - * PSA_ALG_ECDH, where hash is a specific hash. - * \param usage PSA usage flag to check against, must be composed of: - * PSA_KEY_USAGE_SIGN_HASH - * PSA_KEY_USAGE_DECRYPT - * PSA_KEY_USAGE_DERIVE. - * Context key must match all passed usage flags. - * - * \warning Since the set of allowed algorithms and usage flags may be - * expanded in the future, the return value \c 0 should not - * be taken in account for non-allowed algorithms and usage - * flags. - * - * \return 1 if the context can do operations on the given type. - * \return 0 if the context cannot do the operations on the given - * type, for non-allowed algorithms and usage flags, or - * for a context that has been initialized but not set up - * or that has been cleared with mbedtls_pk_free(). - */ -int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, - psa_key_usage_t usage); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -/** - * \brief Verify signature (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used. - * This can be #MBEDTLS_MD_NONE if the signature algorithm - * does not rely on a hash algorithm (non-deterministic - * ECDSA, RSA PKCS#1 v1.5). - * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then - * \p hash is the DigestInfo structure used by RFC 8017 - * §9.2 steps 3–6. If \p md_alg is a valid hash - * algorithm then \p hash is the digest itself, and this - * function calculates the DigestInfo encoding internally. - * \param hash Hash of the message to sign - * \param hash_len Hash length - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid - * signature in \p sig but its length is less than \p sig_len, - * or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) - * to verify RSASSA_PSS signatures. - */ -int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - -/** - * \brief Restartable version of \c mbedtls_pk_verify() - * - * \note Performs the same job as \c mbedtls_pk_verify(), but can - * return early and restart according to the limit set with - * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC - * operations. For RSA, same as \c mbedtls_pk_verify(). - * - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * \param rs_ctx Restart context (NULL to disable restart) - * - * \return See \c mbedtls_pk_verify(), or - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). - */ -int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - mbedtls_pk_restart_ctx *rs_ctx); - -/** - * \brief Verify signature, with options. - * (Includes verification of the padding depending on type.) - * - * \param type Signature type (inc. possible padding type) to verify - * \param options Pointer to type-specific options, or NULL - * \param ctx The PK context to use. It must have been set up. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be - * used for this type of signatures, - * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid - * signature in \p sig but its length is less than \p sig_len, - * or a specific error code. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - * - * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point - * to a mbedtls_pk_rsassa_pss_options structure, - * otherwise it must be NULL. Note that if - * #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not - * verified as PSA_ALG_RSA_PSS_ANY_SALT is used. - */ -int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - -/** - * \brief Make signature, including padding if relevant. - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length - * \param sig Place to write the signature. - * It must have enough room for the signature. - * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. - * You may use a smaller buffer if it is large enough - * given the key type. - * \param sig_size The size of the \p sig buffer in bytes. - * \param sig_len On successful return, - * the number of bytes written to \p sig. - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * - * \return 0 on success, or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * There is no interface in the PK module to make RSASSA-PSS - * signatures yet. - * - * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. - * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. - */ -int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -#if defined(MBEDTLS_PSA_CRYPTO_C) -/** - * \brief Make signature given a signature type. - * - * \param pk_type Signature type. - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length - * \param sig Place to write the signature. - * It must have enough room for the signature. - * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. - * You may use a smaller buffer if it is large enough - * given the key type. - * \param sig_size The size of the \p sig buffer in bytes. - * \param sig_len On successful return, - * the number of bytes written to \p sig. - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * - * \return 0 on success, or a specific error code. - * - * \note When \p pk_type is #MBEDTLS_PK_RSASSA_PSS, - * see #PSA_ALG_RSA_PSS for a description of PSS options used. - * - * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. - * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. - * - */ -int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, - mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -/** - * \brief Restartable version of \c mbedtls_pk_sign() - * - * \note Performs the same job as \c mbedtls_pk_sign(), but can - * return early and restart according to the limit set with - * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC - * operations. For RSA, same as \c mbedtls_pk_sign(). - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) - * \param hash Hash of the message to sign - * \param hash_len Hash length - * \param sig Place to write the signature. - * It must have enough room for the signature. - * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. - * You may use a smaller buffer if it is large enough - * given the key type. - * \param sig_size The size of the \p sig buffer in bytes. - * \param sig_len On successful return, - * the number of bytes written to \p sig. - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * \param rs_ctx Restart context (NULL to disable restart) - * - * \return See \c mbedtls_pk_sign(). - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). - */ -int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_pk_restart_ctx *rs_ctx); - -/** - * \brief Decrypt message (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up - * with a private key. - * \param input Input to decrypt - * \param ilen Input size - * \param output Decrypted output - * \param olen Decrypted message length - * \param osize Size of the output buffer - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/** - * \brief Encrypt message (including padding if relevant). - * - * \param ctx The PK context to use. It must have been set up. - * \param input Message to encrypt - * \param ilen Message size - * \param output Encrypted output - * \param olen Encrypted output length - * \param osize Size of the output buffer - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * - * \note \p f_rng is used for padding generation. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/** - * \brief Check if a public-private pair of keys matches. - * - * \param pub Context holding a public key. - * \param prv Context holding a private (and public) key. - * \param f_rng RNG function, must not be \c NULL. - * \param p_rng RNG parameter - * - * \return \c 0 on success (keys were checked and match each other). - * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not - * be checked - in that case they may or may not match. - * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. - * \return Another non-zero value if the keys do not match. - */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, - const mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -/** - * \brief Export debug information - * - * \param ctx The PK context to use. It must have been initialized. - * \param items Place to write debug items - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); - -/** - * \brief Access the type name - * - * \param ctx The PK context to use. It must have been initialized. - * - * \return Type name on success, or "invalid PK" - */ -const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); - -/** - * \brief Get the key type - * - * \param ctx The PK context to use. It must have been initialized. - * - * \return Type on success. - * \return #MBEDTLS_PK_NONE for a context that has not been set up. - */ -mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); - -#if defined(MBEDTLS_RSA_C) -/** - * Quick access to an RSA context inside a PK context. - * - * \warning This function can only be used when the type of the context, as - * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA. - * Ensuring that is the caller's responsibility. - * Alternatively, you can check whether this function returns NULL. - * - * \return The internal RSA context held by the PK context, or NULL. - */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) -{ - switch (mbedtls_pk_get_type(&pk)) { - case MBEDTLS_PK_RSA: - return (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx); - default: - return NULL; - } -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * Quick access to an EC context inside a PK context. - * - * \warning This function can only be used when the type of the context, as - * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY, - * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA. - * Ensuring that is the caller's responsibility. - * Alternatively, you can check whether this function returns NULL. - * - * \return The internal EC context held by the PK context, or NULL. - */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) -{ - switch (mbedtls_pk_get_type(&pk)) { - case MBEDTLS_PK_ECKEY: - case MBEDTLS_PK_ECKEY_DH: - case MBEDTLS_PK_ECDSA: - return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx); - default: - return NULL; - } -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** \ingroup pk_module */ -/** - * \brief Parse a private key in PEM or DER format - * - * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto - * subsystem must have been initialized by calling - * psa_crypto_init() before calling this function. - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param key Input buffer to parse. - * The buffer must contain the input exactly, with no - * extra trailing material. For PEM, the buffer must - * contain a null-terminated string. - * \param keylen Size of \b key in bytes. - * For PEM data, this includes the terminating null byte, - * so \p keylen must be equal to `strlen(key) + 1`. - * \param pwd Optional password for decryption. - * Pass \c NULL if expecting a non-encrypted key. - * Pass a string of \p pwdlen bytes if expecting an encrypted - * key; a non-encrypted key will also be accepted. - * The empty password is not supported. - * \param pwdlen Size of the password in bytes. - * Ignored if \p pwd is \c NULL. - * \param f_rng RNG function, must not be \c NULL. Used for blinding. - * \param p_rng RNG parameter - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/** \ingroup pk_module */ -/** - * \brief Parse a public key in PEM or DER format - * - * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto - * subsystem must have been initialized by calling - * psa_crypto_init() before calling this function. - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param key Input buffer to parse. - * The buffer must contain the input exactly, with no - * extra trailing material. For PEM, the buffer must - * contain a null-terminated string. - * \param keylen Size of \b key in bytes. - * For PEM data, this includes the terminating null byte, - * so \p keylen must be equal to `strlen(key) + 1`. - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note For compressed points, see #MBEDTLS_ECP_PF_COMPRESSED for - * limitations. - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen); - -#if defined(MBEDTLS_FS_IO) -/** \ingroup pk_module */ -/** - * \brief Load and parse a private key - * - * \note If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto - * subsystem must have been initialized by calling - * psa_crypto_init() before calling this function. - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param path filename to read the private key from - * \param password Optional password to decrypt the file. - * Pass \c NULL if expecting a non-encrypted key. - * Pass a null-terminated string if expecting an encrypted - * key; a non-encrypted key will also be accepted. - * The empty password is not supported. - * \param f_rng RNG function, must not be \c NULL. Used for blinding. - * \param p_rng RNG parameter - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, - const char *path, const char *password, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/** \ingroup pk_module */ -/** - * \brief Load and parse a public key - * - * \param ctx The PK context to fill. It must have been initialized - * but not set up. - * \param path filename to read the public key from - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with - * mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a private key to a PKCS#1 or SEC1 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx PK context which must contain a valid private key. - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_key_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); - -/** - * \brief Write a public key to a SubjectPublicKeyInfo DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx PK context which must contain a valid public or private key. - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a public key to a PEM string - * - * \param ctx PK context which must contain a valid public or private key. - * \param buf Buffer to write to. The output includes a - * terminating null byte. - * \param size Size of the buffer in bytes. - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); - -/** - * \brief Write a private key to a PKCS#1 or SEC1 PEM string - * - * \param ctx PK context which must contain a valid private key. - * \param buf Buffer to write to. The output includes a - * terminating null byte. - * \param size Size of the buffer in bytes. - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_key_pem(const mbedtls_pk_context *ctx, unsigned char *buf, size_t size); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * WARNING: Low-level functions. You probably do not want to use these unless - * you are certain you do ;) - */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** - * \brief Parse a SubjectPublicKeyInfo DER structure - * - * \param p the position in the ASN.1 data - * \param end end of the buffer - * \param pk The PK context to fill. It must have been initialized - * but not set up. - * - * \return 0 if successful, or a specific PK error code - */ -int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk); -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a subjectPublicKey to ASN.1 data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param key PK context which must contain a valid public or private key. - * - * \return the length written or a negative error code - */ -int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key); -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -#if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/** - * \brief Turn an EC or RSA key into an opaque one. - * - * \warning This is a temporary utility function for tests. It might - * change or be removed at any time without notice. - * - * \param pk Input: the EC or RSA key to import to a PSA key. - * Output: a PK context wrapping that PSA key. - * \param key Output: a PSA key identifier. - * It's the caller's responsibility to call - * psa_destroy_key() on that key identifier after calling - * mbedtls_pk_free() on the PK context. - * \param alg The algorithm to allow for use with that key. - * \param usage The usage to allow for use with that key. - * \param alg2 The secondary algorithm to allow for use with that key. - * - * \return \c 0 if successful. - * \return An Mbed TLS error code otherwise. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PK_H */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h index f7515b6de3..73506f6bab 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h @@ -10,6 +10,8 @@ void *mbedtls_platform_memset(void *, int, size_t); void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); void mbedtls_platform_random_delay(void); uint32_t mbedtls_platform_random_in_range(uint32_t num); +int mbedtls_platform_memmove(void *dst, const void *src, size_t num); +int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num); #endif // defined(SL_MBEDTLS_USE_TINYCRYPT) #endif // TINYCRYPT_PLATFORM_UTIL_H \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/ecc.c b/matter/mbedtls/tinycrypt/src/ecc.c index afcd406a0a..88f9234574 100644 --- a/matter/mbedtls/tinycrypt/src/ecc.c +++ b/matter/mbedtls/tinycrypt/src/ecc.c @@ -1,8 +1,10 @@ /* ecc.c - TinyCrypt implementation of common ECC functions */ + /* * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. * SPDX-License-Identifier: BSD-3-Clause */ + /* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. @@ -54,99 +56,132 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif + #if defined(SL_MBEDTLS_USE_TINYCRYPT) -#include #include -#include -#include -#include +#include "mbedtls/platform_util.h" +#include "mbedtls/sha256.h" +#include +#include "mbedtls/platform_util.h" + #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM #ifndef asm #define asm __asm #endif #endif /* MBEDTLS_OPTIMIZE_TINYCRYPT_ASM */ -#include "mbedtls/compat-2.x.h" - /* Parameters for curve NIST P-256 aka secp256r1 */ -const uECC_word_t curve_p[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), - BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), - BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) }; -const uECC_word_t curve_n[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), - BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), - BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), - BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) }; +const uECC_word_t curve_p[NUM_ECC_WORDS] = { + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) +}; +const uECC_word_t curve_n[NUM_ECC_WORDS] = { + BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) +}; const uECC_word_t curve_G[2 * NUM_ECC_WORDS] = { - BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), - BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), - BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), - BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) + BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), + BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), + BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), + BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), + BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) +}; +const uECC_word_t curve_b[NUM_ECC_WORDS] = { + BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }; -const uECC_word_t curve_b[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), - BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), - BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), - BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }; -static int uECC_update_param_sha256(mbedtls_sha256_context *ctx, const uECC_word_t val[NUM_ECC_WORDS]) + +static int uECC_update_param_sha256(mbedtls_sha256_context *ctx, + const uECC_word_t val[NUM_ECC_WORDS]) { - uint8_t bytes[NUM_ECC_BYTES]; - uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val); - return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES); + uint8_t bytes[NUM_ECC_BYTES]; + + uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val); + return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES); } + static int uECC_compute_param_sha256(unsigned char output[32]) { - int ret = UECC_FAILURE; - mbedtls_sha256_context ctx; - mbedtls_sha256_init(&ctx); - if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) { - goto exit; - } - if (uECC_update_param_sha256(&ctx, curve_p) != 0 || uECC_update_param_sha256(&ctx, curve_n) != 0 - || uECC_update_param_sha256(&ctx, curve_G) != 0 || uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 - || uECC_update_param_sha256(&ctx, curve_b) != 0) { - goto exit; - } - if (mbedtls_sha256_finish_ret(&ctx, output) != 0) { - goto exit; - } - ret = UECC_SUCCESS; + int ret = UECC_FAILURE; + mbedtls_sha256_context ctx; + + mbedtls_sha256_init( &ctx ); + + if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) { + goto exit; + } + + if (uECC_update_param_sha256(&ctx, curve_p) != 0 || + uECC_update_param_sha256(&ctx, curve_n) != 0 || + uECC_update_param_sha256(&ctx, curve_G) != 0 || + uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 || + uECC_update_param_sha256(&ctx, curve_b) != 0) + { + goto exit; + } + + if (mbedtls_sha256_finish_ret(&ctx, output) != 0) { + goto exit; + } + + ret = UECC_SUCCESS; + exit: - mbedtls_sha256_free(&ctx); - return ret; + mbedtls_sha256_free( &ctx ); + + return ret; } + /* * Check integrity of curve parameters. * Return 0 if everything's OK, non-zero otherwise. */ static int uECC_check_curve_integrity(void) { - unsigned char computed[32]; - static const unsigned char reference[32] = { - 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1, 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92, - 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6, 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49, - }; - int diff = 0; - unsigned char tmp1, tmp2; - volatile unsigned i; - if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) { - return UECC_FAILURE; - } - for (i = 0; i < 32; i++) { - /* make sure the order of volatile accesses is well-defined */ - tmp1 = computed[i]; - tmp2 = reference[i]; - diff |= tmp1 ^ tmp2; - } - /* i should be 32 */ - mbedtls_platform_random_delay(); - diff |= i ^ 32; - return diff; + unsigned char computed[32]; + static const unsigned char reference[32] = { + 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1, + 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92, + 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6, + 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49, + }; + int diff = 0; + unsigned char tmp1, tmp2; + volatile unsigned i; + + if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) { + return UECC_FAILURE; + } + + for (i = 0; i < 32; i++) { + /* make sure the order of volatile accesses is well-defined */ + tmp1 = computed[i]; + tmp2 = reference[i]; + diff |= tmp1 ^ tmp2; + } + + /* i should be 32 */ + mbedtls_platform_random_delay(); + diff |= i ^ 32; + + return diff; } + /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform * has access to enough entropy in order to feed the PRNG regularly. */ #if default_RNG_defined @@ -154,22 +189,27 @@ static uECC_RNG_Function g_rng_function = &default_CSPRNG; #else static uECC_RNG_Function g_rng_function = 0; #endif + void uECC_set_rng(uECC_RNG_Function rng_function) { - g_rng_function = rng_function; + g_rng_function = rng_function; } + uECC_RNG_Function uECC_get_rng(void) { - return g_rng_function; + return g_rng_function; } + int uECC_curve_private_key_size(void) { - return BITS_TO_BYTES(NUM_ECC_BITS); + return BITS_TO_BYTES(NUM_ECC_BITS); } + int uECC_curve_public_key_size(void) { - return 2 * NUM_ECC_BYTES; + return 2 * NUM_ECC_BYTES; } + #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM __asm void uECC_vli_clear(uECC_word_t *vli) { @@ -177,13 +217,20 @@ __asm void uECC_vli_clear(uECC_word_t *vli) #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif #if !defined __thumb__ || __TARGET_ARCH_THUMB < 4 - MOVS r1, #0 MOVS r2, #0 STMIA r0 !, { r1, r2 } STMIA r0 !, { r1, r2 } STMIA r0 !, { r1, r2 } STMIA r0 !, - { r1, r2 } BX lr + MOVS r1,#0 + MOVS r2,#0 + STMIA r0!,{r1,r2} + STMIA r0!,{r1,r2} + STMIA r0!,{r1,r2} + STMIA r0!,{r1,r2} + BX lr #else - MOVS r1, #0 STRD r1, r1, - [r0, #0] // Only Thumb2 STRD can store same reg twice, not ARM - STRD r1, - r1, [r0, #8] STRD r1, r1, [r0, #16] STRD r1, r1, [r0, #24] BX lr + MOVS r1,#0 + STRD r1,r1,[r0,#0] // Only Thumb2 STRD can store same reg twice, not ARM + STRD r1,r1,[r0,#8] + STRD r1,r1,[r0,#16] + STRD r1,r1,[r0,#24] + BX lr #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ @@ -193,264 +240,329 @@ void uECC_vli_clear(uECC_word_t *vli) #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif #if !defined __thumb__ || !defined __thumb2__ - register uECC_word_t *r0 asm("r0") = vli; - register uECC_word_t r1 asm("r1") = 0; - register uECC_word_t r2 asm("r2") = 0; - asm volatile(".syntax unified \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - "STMIA r0!,{r1,r2} \n\t" - ".syntax divided \n\t" - : "+r"(r0) - : "r"(r1), "r"(r2) - : "memory" + register uECC_word_t *r0 asm("r0") = vli; + register uECC_word_t r1 asm("r1") = 0; + register uECC_word_t r2 asm("r2") = 0; + asm volatile ( + ".syntax unified \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + "STMIA r0!,{r1,r2} \n\t" + ".syntax divided \n\t" + : "+r" (r0) + : "r" (r1), "r" (r2) + : "memory" #else - register uECC_word_t *r0 asm("r0") = vli; - register uECC_word_t r1 asm("r1") = 0; - asm volatile("STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM - "STRD r1,r1,[r0,#8] \n\t" - "STRD r1,r1,[r0,#16] \n\t" - "STRD r1,r1,[r0,#24] \n\t" - : - : "r"(r0), "r"(r1) - : "memory" + register uECC_word_t *r0 asm("r0") = vli; + register uECC_word_t r1 asm("r1") = 0; + asm volatile ( + "STRD r1,r1,[r0,#0] \n\t" // Only Thumb2 STRD can store same reg twice, not ARM + "STRD r1,r1,[r0,#8] \n\t" + "STRD r1,r1,[r0,#16] \n\t" + "STRD r1,r1,[r0,#24] \n\t" + : + : "r" (r0), "r" (r1) + : "memory" #endif - ); + ); } #else void uECC_vli_clear(uECC_word_t *vli) { - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - vli[i] = 0; - } + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + vli[i] = 0; + } } #endif + #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM __asm uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - LDMIA r0 !, { r1, r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0 !, { r2, r3 } ORRS r1, r2 ORRS r1, r3 LDMIA r0, - { r0, r2, r3 } ORRS r1, r0 ORRS r1, r2 ORRS r1, r3 RSBS r1, r1, -# 0 // C set if zero - MOVS r0, -# 0 ADCS r0, - r0 BX lr +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + LDMIA r0!,{r1,r2,r3} + ORRS r1,r2 + ORRS r1,r3 + LDMIA r0!,{r2,r3} + ORRS r1,r2 + ORRS r1,r3 + LDMIA r0,{r0,r2,r3} + ORRS r1,r0 + ORRS r1,r2 + ORRS r1,r3 + RSBS r1,r1,#0 // C set if zero + MOVS r0,#0 + ADCS r0,r0 + BX lr #else - LDMIA r0 !, { r1, r2, r3, ip } ORRS r1, r2 ORRS r1, r3 ORRS r1, ip LDMIA r0, { r0, r2, r3, ip } ORRS r1, r0 ORRS r1, - r2 ORRS r1, r3 ORRS r1, - ip + LDMIA r0!,{r1,r2,r3,ip} + ORRS r1,r2 + ORRS r1,r3 + ORRS r1,ip + LDMIA r0,{r0,r2,r3,ip} + ORRS r1,r0 + ORRS r1,r2 + ORRS r1,r3 + ORRS r1,ip #ifdef __ARM_FEATURE_CLZ - CLZ r0, - r1 // 32 if zero - LSRS r0, - r0, -# 5 + CLZ r0,r1 // 32 if zero + LSRS r0,r0,#5 #else - RSBS r1, - r1, -# 0 // C set if zero - MOVS r0, -# 0 ADCS r0, - r0 + RSBS r1,r1,#0 // C set if zero + MOVS r0,#0 + ADCS r0,r0 #endif - BX lr + BX lr #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { - uECC_word_t ret; + uECC_word_t ret; #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif #if defined __thumb__ && !defined __thumb2__ - register uECC_word_t r1 asm("r1"); - register uECC_word_t r2 asm("r2"); - register uECC_word_t r3 asm("r3"); - asm volatile(".syntax unified \n\t" - "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "LDMIA %[vli]!,{%[r2],%[r3]} \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t" - "ORRS %[r1],%[vli] \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "RSBS %[r1],%[r1],#0 \n\t" // C set if zero - "MOVS %[ret],#0 \n\t" - "ADCS %[ret],r0 \n\t" - ".syntax divided \n\t" - : [ret] "=r"(ret), [r1] "=r"(r1), [r2] "=r"(r2), [r3] "=r"(r3) - : [vli] "[ret]"(vli) - : "cc", "memory"); + register uECC_word_t r1 asm ("r1"); + register uECC_word_t r2 asm ("r2"); + register uECC_word_t r3 asm ("r3"); + asm volatile ( + ".syntax unified \n\t" + "LDMIA %[vli]!,{%[r1],%[r2],%[r3]} \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "LDMIA %[vli]!,{%[r2],%[r3]} \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "LDMIA %[vli],{%[vli],%[r2],%[r3]} \n\t" + "ORRS %[r1],%[vli] \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "RSBS %[r1],%[r1],#0 \n\t" // C set if zero + "MOVS %[ret],#0 \n\t" + "ADCS %[ret],r0 \n\t" + ".syntax divided \n\t" + : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3) + : [vli]"[ret]" (vli) + : "cc", "memory" + ); #else - register uECC_word_t r1 asm("r1"); - register uECC_word_t r2 asm("r2"); - register uECC_word_t r3 asm("r3"); - register uECC_word_t ip asm("ip"); - asm volatile("LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "ORRS %[r1],%[ip] \n\t" - "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t" - "ORRS %[r1],%[vli] \n\t" - "ORRS %[r1],%[r2] \n\t" - "ORRS %[r1],%[r3] \n\t" - "ORRS %[r1],%[ip] \n\t" + register uECC_word_t r1 asm ("r1"); + register uECC_word_t r2 asm ("r2"); + register uECC_word_t r3 asm ("r3"); + register uECC_word_t ip asm ("ip"); + asm volatile ( + "LDMIA %[vli]!,{%[r1],%[r2],%[r3],%[ip]}\n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "ORRS %[r1],%[ip] \n\t" + "LDMIA %[vli],{%[vli],%[r2],%[r3],%[ip]}\n\t" + "ORRS %[r1],%[vli] \n\t" + "ORRS %[r1],%[r2] \n\t" + "ORRS %[r1],%[r3] \n\t" + "ORRS %[r1],%[ip] \n\t" #if __ARM_ARCH >= 5 - "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero - "LSRS %[ret],%[ret],#5 \n\t" + "CLZ %[ret],%[r1] \n\t" // r0 = 32 if zero + "LSRS %[ret],%[ret],#5 \n\t" #else - "RSBS %[r1],%[r1],#0 \n\t" // C set if zero - "MOVS %[ret],#0 \n\t" - "ADCS %[ret],r0 \n\t" + "RSBS %[r1],%[r1],#0 \n\t" // C set if zero + "MOVS %[ret],#0 \n\t" + "ADCS %[ret],r0 \n\t" #endif - : [ret] "=r"(ret), [r1] "=r"(r1), [r2] "=r"(r2), [r3] "=r"(r3), [ip] "=r"(ip) - : [vli] "[ret]"(vli) - : "cc", "memory"); + : [ret]"=r" (ret), [r1]"=r" (r1), [r2]"=r" (r2), [r3]"=r" (r3), [ip]"=r" (ip) + : [vli]"[ret]" (vli) + : "cc", "memory" + ); #endif - return ret; + return ret; } #else uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { - uECC_word_t bits = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - bits |= vli[i]; - } - return (bits == 0); + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + bits |= vli[i]; + } + return (bits == 0); } #endif + uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { - return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); + return (vli[bit >> uECC_WORD_BITS_SHIFT] & + ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); } + /* Counts the number of words in vli. */ static wordcount_t vli_numDigits(const uECC_word_t *vli) { - wordcount_t i; - /* Search from the end until we find a non-zero digit. We do it in reverse + + wordcount_t i; + /* Search from the end until we find a non-zero digit. We do it in reverse * because we expect that most digits will be nonzero. */ - for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) { - } - return (i + 1); + for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) { + } + + return (i + 1); } + bitcount_t uECC_vli_numBits(const uECC_word_t *vli) { - uECC_word_t i; - uECC_word_t digit; - wordcount_t num_digits = vli_numDigits(vli); - if (num_digits == 0) { - return 0; - } - digit = vli[num_digits - 1]; + + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli); + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; #if defined __GNUC__ || defined __clang__ || defined __CC_ARM - i = uECC_WORD_BITS - __builtin_clz(digit); + i = uECC_WORD_BITS - __builtin_clz(digit); #else - for (i = 0; digit; ++i) { - digit >>= 1; - } + for (i = 0; digit; ++i) { + digit >>= 1; + } #endif - return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); } + void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src) { - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - dest[i] = src[i]; - } + wordcount_t i; + + for (i = 0; i < NUM_ECC_WORDS; ++i) { + dest[i] = src[i]; + } } -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right) + +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right) { - wordcount_t i; - for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { - if (left[i] > right[i]) { - return 1; - } else if (left[i] < right[i]) { - return -1; - } - } - return 0; + wordcount_t i; + + for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; } + uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right) { - uECC_word_t diff = 0; - uECC_word_t flow_monitor = 0; - uECC_word_t tmp1, tmp2; - volatile int i; - /* Start from a random location and check the correct number of iterations */ - int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS); - for (i = start_offset; i < NUM_ECC_WORDS; ++i) { - tmp1 = left[i]; - tmp2 = right[i]; - flow_monitor++; - diff |= (tmp1 ^ tmp2); - } - for (i = 0; i < start_offset; ++i) { - tmp1 = left[i]; - tmp2 = right[i]; - flow_monitor++; - diff |= (tmp1 ^ tmp2); - } - /* Random delay to increase security */ - mbedtls_platform_random_delay(); - /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */ - return (diff | (flow_monitor ^ NUM_ECC_WORDS)); + + uECC_word_t diff = 0; + uECC_word_t flow_monitor = 0; + uECC_word_t tmp1, tmp2; + volatile int i; + + /* Start from a random location and check the correct number of iterations */ + int start_offset = mbedtls_platform_random_in_range(NUM_ECC_WORDS); + + for (i = start_offset; i < NUM_ECC_WORDS; ++i) { + tmp1 = left[i]; + tmp2 = right[i]; + flow_monitor++; + diff |= (tmp1 ^ tmp2); + } + + for (i = 0; i < start_offset; ++i) { + tmp1 = left[i]; + tmp2 = right[i]; + flow_monitor++; + diff |= (tmp1 ^ tmp2); + } + + /* Random delay to increase security */ + mbedtls_platform_random_delay(); + + /* Return 0 only when diff is 0 and flow_counter is equal to NUM_ECC_WORDS */ + return (diff | (flow_monitor ^ NUM_ECC_WORDS)); } + uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) { - return (p_true * (cond)) | (p_false * (cond ^ 1)); + return (p_true*(cond)) | (p_false*(cond ^ 1)); } + /* Computes result = left - right, returning borrow, in constant time. * Can modify in place. */ #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +__asm uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{ r4 - r6, lr } FRAME PUSH{ r4 - r6, lr } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SUBS r3, r5 SBCS r4, - r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, - { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, - { r3, r4 } LDMIA r2 !, { r5, r6 } SBCS r3, r5 SBCS r4, r6 STMIA r0 !, { r3, r4 } SBCS r0, - r0 // r0 := r0 - r0 - borrow = -borrow - RSBS r0, - r0, -# 0 // r0 := borrow - POP{ r4 - r6, pc } +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH {r4-r6,lr} + FRAME PUSH {r4-r6,lr} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + SUBS r3,r5 + SBCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + SBCS r3,r5 + SBCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + SBCS r3,r5 + SBCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + SBCS r3,r5 + SBCS r4,r6 + STMIA r0!,{r3,r4} + SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow + RSBS r0,r0,#0 // r0 := borrow + POP {r4-r6,pc} #else - PUSH{ r4 - r8, lr } FRAME PUSH{ r4 - r8, lr } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, { r7, r8, r12, lr } SUBS r3, - r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, lr STMIA r0 !, { r3 - r6 } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, - { r7, r8, r12, lr } SBCS r3, r7 SBCS r4, r8 SBCS r5, r12 SBCS r6, lr STMIA r0 !, { r3 - r6 } SBCS r0, - r0 // r0 := r0 - r0 - borrow = -borrow - RSBS r0, - r0, -# 0 // r0 := borrow - POP - { - r4 - r8, pc - } + PUSH {r4-r8,lr} + FRAME PUSH {r4-r8,lr} + LDMIA r1!,{r3-r6} + LDMIA r2!,{r7,r8,r12,lr} + SUBS r3,r7 + SBCS r4,r8 + SBCS r5,r12 + SBCS r6,lr + STMIA r0!,{r3-r6} + LDMIA r1!,{r3-r6} + LDMIA r2!,{r7,r8,r12,lr} + SBCS r3,r7 + SBCS r4,r8 + SBCS r5,r12 + SBCS r6,lr + STMIA r0!,{r3-r6} + SBCS r0,r0 // r0 := r0 - r0 - borrow = -borrow + RSBS r0,r0,#0 // r0 := borrow + POP {r4-r8,pc} #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif - register uECC_word_t *r0 asm("r0") = result; - register const uECC_word_t *r1 asm("r1") = left; - register const uECC_word_t *r2 asm("r2") = right; - asm volatile( + register uECC_word_t *r0 asm ("r0") = result; + register const uECC_word_t *r1 asm ("r1") = left; + register const uECC_word_t *r2 asm ("r2") = right; + asm volatile ( #if defined __thumb__ && !defined __thumb2__ ".syntax unified \n\t" "LDMIA r1!,{r3,r4} \n\t" @@ -476,7 +588,7 @@ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uEC "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow "RSBS r0,r0,#0 \n\t" // r0 := borrow ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "r4", "r5", "r6", "cc", "memory" #else @@ -496,64 +608,96 @@ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uEC "STMIA r0!,{r3-r6} \n\t" "SBCS r0,r0 \n\t" // r0 := r0 - r0 - borrow = -borrow "RSBS r0,r0,#0 \n\t" // r0 := borrow - : "+r"(r0), "+r"(r1), "+r"(r2) + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" #endif - ); - return (uECC_word_t)r0; + ); + return (uECC_word_t) r0; } #else -uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - uECC_word_t diff = left[i] - right[i] - borrow; - uECC_word_t val = (diff > left[i]); - borrow = cond_set(val, borrow, (diff != left[i])); - result[i] = diff; - } - return borrow; + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + uECC_word_t val = (diff > left[i]); + borrow = cond_set(val, borrow, (diff != left[i])); + + result[i] = diff; + } + return borrow; } #endif + /* Computes result = left + right, returning carry, in constant time. * Can modify in place. */ #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM -static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +static __asm uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{ r4 - r6, lr } FRAME PUSH{ r4 - r6, lr } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADDS r3, r5 ADCS r4, - r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, - { r3, r4 } LDMIA r1 !, { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, { r3, r4 } LDMIA r1 !, - { r3, r4 } LDMIA r2 !, { r5, r6 } ADCS r3, r5 ADCS r4, r6 STMIA r0 !, { r3, r4 } MOVS r0, -# 0 // does not affect C flag - ADCS r0, - r0 // r0 := 0 + 0 + C = carry - POP{ r4 - r6, pc } +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH {r4-r6,lr} + FRAME PUSH {r4-r6,lr} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + ADDS r3,r5 + ADCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + ADCS r3,r5 + ADCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + ADCS r3,r5 + ADCS r4,r6 + STMIA r0!,{r3,r4} + LDMIA r1!,{r3,r4} + LDMIA r2!,{r5,r6} + ADCS r3,r5 + ADCS r4,r6 + STMIA r0!,{r3,r4} + MOVS r0,#0 // does not affect C flag + ADCS r0,r0 // r0 := 0 + 0 + C = carry + POP {r4-r6,pc} #else - PUSH{ r4 - r8, lr } FRAME PUSH{ r4 - r8, lr } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, { r7, r8, r12, lr } ADDS r3, - r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, lr STMIA r0 !, { r3 - r6 } LDMIA r1 !, { r3 - r6 } LDMIA r2 !, - { r7, r8, r12, lr } ADCS r3, r7 ADCS r4, r8 ADCS r5, r12 ADCS r6, lr STMIA r0 !, { r3 - r6 } MOVS r0, -# 0 // does not affect C flag - ADCS r0, - r0 // r0 := 0 + 0 + C = carry - POP - { - r4 - r8, pc - } + PUSH {r4-r8,lr} + FRAME PUSH {r4-r8,lr} + LDMIA r1!,{r3-r6} + LDMIA r2!,{r7,r8,r12,lr} + ADDS r3,r7 + ADCS r4,r8 + ADCS r5,r12 + ADCS r6,lr + STMIA r0!,{r3-r6} + LDMIA r1!,{r3-r6} + LDMIA r2!,{r7,r8,r12,lr} + ADCS r3,r7 + ADCS r4,r8 + ADCS r5,r12 + ADCS r6,lr + STMIA r0!,{r3-r6} + MOVS r0,#0 // does not affect C flag + ADCS r0,r0 // r0 := 0 + 0 + C = carry + POP {r4-r8,pc} #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { - register uECC_word_t *r0 asm("r0") = result; - register const uECC_word_t *r1 asm("r1") = left; - register const uECC_word_t *r2 asm("r2") = right; - asm volatile( + register uECC_word_t *r0 asm ("r0") = result; + register const uECC_word_t *r1 asm ("r1") = left; + register const uECC_word_t *r2 asm ("r2") = right; + + asm volatile ( #if defined __thumb__ && !defined __thumb2__ ".syntax unified \n\t" "LDMIA r1!,{r3,r4} \n\t" @@ -576,10 +720,10 @@ static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, co "ADCS r3,r5 \n\t" "ADCS r4,r6 \n\t" "STMIA r0!,{r3,r4} \n\t" - "MOVS r0,#0 \n\t" // does not affect C flag - "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry + "MOVS r0,#0 \n\t" // does not affect C flag + "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "r4", "r5", "r6", "cc", "memory" #else @@ -597,105 +741,120 @@ static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, co "ADCS r5,r12 \n\t" "ADCS r6,lr \n\t" "STMIA r0!,{r3-r6} \n\t" - "MOVS r0,#0 \n\t" // does not affect C flag - "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry - : "+r"(r0), "+r"(r1), "+r"(r2) + "MOVS r0,#0 \n\t" // does not affect C flag + "ADCS r0,r0 \n\t" // r0 := 0 + 0 + C = carry + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "r4", "r5", "r6", "r7", "r8", "r12", "lr", "cc", "memory" #endif - ); - return (uECC_word_t)r0; + ); + return (uECC_word_t) r0; } #else -static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) +static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { - uECC_word_t carry = 0; - wordcount_t i; - for (i = 0; i < NUM_ECC_WORDS; ++i) { - uECC_word_t sum = left[i] + right[i] + carry; - uECC_word_t val = (sum < left[i]); - carry = cond_set(val, carry, (sum != left[i])); - result[i] = sum; - } - return carry; + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < NUM_ECC_WORDS; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + uECC_word_t val = (sum < left[i]); + carry = cond_set(val, carry, (sum != left[i])); + result[i] = sum; + } + return carry; } #endif + cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t neg = uECC_vli_sub(tmp, left, right); - uECC_word_t equal = uECC_vli_isZero(tmp); - return ((equal ^ 1) - 2 * neg); + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t neg = uECC_vli_sub(tmp, left, right); + uECC_word_t equal = uECC_vli_isZero(tmp); + return ((equal ^ 1) - 2 * neg); } + /* Computes vli = vli >> 1. */ #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM static __asm void uECC_vli_rshift1(uECC_word_t *vli) { -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - // RRX instruction is not available, so although we - // can use C flag, it's not that effective. Does at - // least save one working register, meaning we don't need stack - MOVS r3, -# 0 // initial carry = 0 - MOVS r2, -#__cpp(4 * (NUM_ECC_WORDS - 1)) 01 LDR r1, [r0, r2] LSRS r1, r1, -# 1 // r2 = word >> 1 - ORRS r1, - r3 // merge in the previous carry - STR r1, - [r0, r2] ADCS r3, - r3 // put C into bottom bit of r3 - LSLS r3, - r3, -# 31 // shift it up to the top ready for next word - SUBS r2, r2, #4 BPL % B01 BX lr +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 +// RRX instruction is not available, so although we +// can use C flag, it's not that effective. Does at +// least save one working register, meaning we don't need stack + MOVS r3,#0 // initial carry = 0 + MOVS r2,#__cpp(4 * (NUM_ECC_WORDS - 1)) +01 LDR r1,[r0,r2] + LSRS r1,r1,#1 // r2 = word >> 1 + ORRS r1,r3 // merge in the previous carry + STR r1,[r0,r2] + ADCS r3,r3 // put C into bottom bit of r3 + LSLS r3,r3,#31 // shift it up to the top ready for next word + SUBS r2,r2,#4 + BPL %B01 + BX lr #else #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif - // Smooth multiword operation, lots of 32-bit instructions - ADDS r0, #32 LDMDB r0, { r1 - r3, ip } LSRS ip, ip, #1 RRXS r3, r3 RRXS r2, r2 RRXS r1, r1 STMDB r0 !, - { r1 - r3, ip } LDMDB r0, { r1 - r3, ip } RRXS ip, ip RRXS r3, r3 RRXS r2, r2 RRX r1, r1 STMDB r0 !, - { r1 - r3, ip } BX lr +// Smooth multiword operation, lots of 32-bit instructions + ADDS r0,#32 + LDMDB r0,{r1-r3,ip} + LSRS ip,ip,#1 + RRXS r3,r3 + RRXS r2,r2 + RRXS r1,r1 + STMDB r0!,{r1-r3,ip} + LDMDB r0,{r1-r3,ip} + RRXS ip,ip + RRXS r3,r3 + RRXS r2,r2 + RRX r1,r1 + STMDB r0!,{r1-r3,ip} + BX lr #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ && defined __thumb2__ static void uECC_vli_rshift1(uECC_word_t *vli) { - register uECC_word_t *r0 asm("r0") = vli; + register uECC_word_t *r0 asm ("r0") = vli; #if NUM_ECC_WORDS != 8 #error adjust ARM assembly to handle NUM_ECC_WORDS != 8 #endif - asm volatile("ADDS r0,#32 \n\t" - "LDMDB r0,{r1-r3,ip} \n\t" - "LSRS ip,ip,#1 \n\t" - "RRXS r3,r3 \n\t" - "RRXS r2,r2 \n\t" - "RRXS r1,r1 \n\t" - "STMDB r0!,{r1-r3,ip} \n\t" - "LDMDB r0,{r1-r3,ip} \n\t" - "RRXS ip,ip \n\t" - "RRXS r3,r3 \n\t" - "RRXS r2,r2 \n\t" - "RRX r1,r1 \n\t" - "STMDB r0!,{r1-r3,ip} \n\t" - : "+r"(r0) - : - : "r1", "r2", "r3", "ip", "cc", "memory"); + asm volatile ( + "ADDS r0,#32 \n\t" + "LDMDB r0,{r1-r3,ip} \n\t" + "LSRS ip,ip,#1 \n\t" + "RRXS r3,r3 \n\t" + "RRXS r2,r2 \n\t" + "RRXS r1,r1 \n\t" + "STMDB r0!,{r1-r3,ip} \n\t" + "LDMDB r0,{r1-r3,ip} \n\t" + "RRXS ip,ip \n\t" + "RRXS r3,r3 \n\t" + "RRXS r2,r2 \n\t" + "RRX r1,r1 \n\t" + "STMDB r0!,{r1-r3,ip} \n\t" + : "+r" (r0) + : + : "r1", "r2", "r3", "ip", "cc", "memory" + ); } #else static void uECC_vli_rshift1(uECC_word_t *vli) { - uECC_word_t *end = vli; - uECC_word_t carry = 0; - vli += NUM_ECC_WORDS; - while (vli-- > end) { - uECC_word_t temp = *vli; - *vli = (temp >> 1) | carry; - carry = temp << (uECC_WORD_BITS - 1); - } + uECC_word_t *end = vli; + uECC_word_t carry = 0; + + vli += NUM_ECC_WORDS; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } } #endif + /* Compute a * b + r, where r is a triple-word with high-order word r[2] and * low-order word r[0], and store the result in the same triple-word. * @@ -707,69 +866,60 @@ static void uECC_vli_rshift1(uECC_word_t *vli) #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __CC_ARM static __asm void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { -#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 - PUSH{ r4 - r5 } FRAME PUSH{ r4 - r5 } // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 - // Separate operands into halfwords - UXTH r3, - r0 // r3 := a.lo - LSRS r4, - r0, -# 16 // r4 := a.hi - UXTH r5, - r1 // r5 := b.lo - LSRS r1, - r1, -# 16 // r1 := b.hi +#if defined __thumb__ && __TARGET_ARCH_THUMB < 4 + PUSH {r4-r5} + FRAME PUSH {r4-r5} + // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 + // Separate operands into halfwords + UXTH r3,r0 // r3 := a.lo + LSRS r4,r0,#16 // r4 := a.hi + UXTH r5,r1 // r5 := b.lo + LSRS r1,r1,#16 // r1 := b.hi // Multiply halfword pairs - MOVS r0, r3 MULS r0, r5, - r0 // r0 := a.lo * b.lo - MULS r3, - r1, - r3 // r3 := a.lo * b.hi - MULS r5, - r4, - r5 // r5 := a.hi * b.lo - MULS r1, - r4, - r1 // r1 := a.hi * b.hi - // Split, shift and add a.lo * b.hi - LSRS r4, - r3, -# 16 // r4 := (a.lo * b.hi).hi - LSLS r3, r3, -# 16 // r3 := (a.lo * b.hi).lo - ADDS r0, r0, - r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo - ADCS r1, - r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry - // Split, shift and add a.hi * b.lo - LSRS r4, - r5, -# 16 // r4 := (a.hi * b.lo).hi - LSLS r5, r5, -# 16 // r5 := (a.hi * b.lo).lo - ADDS r0, r0, - r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo - ADCS r1, - r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries - // Finally add r[] - LDMIA r2 !, - { r3, r4, r5 } ADDS r3, r3, r0 ADCS r4, r1 MOVS r0, #0 ADCS r5, r0 SUBS r2, #12 STMIA r2 !, - { r3, r4, r5 } POP{ r4 - r5 } FRAME POP{ r4 - r5 } BX lr + MOVS r0,r3 + MULS r0,r5,r0 // r0 := a.lo * b.lo + MULS r3,r1,r3 // r3 := a.lo * b.hi + MULS r5,r4,r5 // r5 := a.hi * b.lo + MULS r1,r4,r1 // r1 := a.hi * b.hi + // Split, shift and add a.lo * b.hi + LSRS r4,r3,#16 // r4 := (a.lo * b.hi).hi + LSLS r3,r3,#16 // r3 := (a.lo * b.hi).lo + ADDS r0,r0,r3 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + carry + // Split, shift and add a.hi * b.lo + LSRS r4,r5,#16 // r4 := (a.hi * b.lo).hi + LSLS r5,r5,#16 // r5 := (a.hi * b.lo).lo + ADDS r0,r0,r5 // r0 := a.lo * b.lo + (a.lo * b.hi).lo + (a.hi * b.lo).lo + ADCS r1,r4 // r1 := a.hi * b.hi + (a.lo * b.hi).hi + (a.hi * b.lo).hi + carries + // Finally add r[] + LDMIA r2!,{r3,r4,r5} + ADDS r3,r3,r0 + ADCS r4,r1 + MOVS r0,#0 + ADCS r5,r0 + SUBS r2,#12 + STMIA r2!,{r3,r4,r5} + POP {r4-r5} + FRAME POP {r4-r5} + BX lr #else - UMULL r3, ip, r0, - r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn - LDMIA r2, - { r0, r1 } ADDS r0, r0, r3 LDR r3, [r2, #8] ADCS r1, r1, ip ADC r3, r3, #0 STMIA r2 !, { r0, r1, r3 } BX lr + UMULL r3,ip,r0,r1 // pre-ARMv6 requires Rd[Lo|Hi] != Rn + LDMIA r2,{r0,r1} + ADDS r0,r0,r3 + LDR r3,[r2,#8] + ADCS r1,r1,ip + ADC r3,r3,#0 + STMIA r2!,{r0,r1,r3} + BX lr #endif } #elif defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM && defined __GNUC__ && defined __arm__ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { - register uECC_word_t r0 asm("r0") = a; - register uECC_word_t r1 asm("r1") = b; - register uECC_word_t *r2 asm("r2") = r; - asm volatile( + register uECC_word_t r0 asm ("r0") = a; + register uECC_word_t r1 asm ("r1") = b; + register uECC_word_t *r2 asm ("r2") = r; + asm volatile ( #if defined __thumb__ && !defined(__thumb2__) ".syntax unified \n\t" // __ARM_common_mul_uu replacement - inline, faster, don't touch R2 @@ -803,7 +953,7 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) "SUBS r2,#12 \n\t" "STMIA r2!,{r3,r4,r5} \n\t" ".syntax divided \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "r4", "r5", "ip", "cc", "memory" #else @@ -814,23 +964,25 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) "ADCS r1,r1,ip \n\t" "ADC r3,r3,#0 \n\t" "STMIA r2!,{r0,r1,r3} \n\t" - : "+r"(r0), "+r"(r1), "+r"(r2) + : "+r" (r0), "+r" (r1), "+r" (r2) : : "r3", "ip", "cc", "memory" #endif - ); + ); } #else static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) { - uECC_dword_t p = (uECC_dword_t)a * b; - uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0]; - r01 += p; - r[2] += (r01 < p); - r[1] = r01 >> uECC_WORD_BITS; - r[0] = (uECC_word_t)r01; + + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(r[1]) << uECC_WORD_BITS) | r[0]; + r01 += p; + r[2] += (r01 < p); + r[1] = r01 >> uECC_WORD_BITS; + r[0] = (uECC_word_t)r01; } #endif + /* State for implementing random delays in uECC_vli_mult_rnd(). * * The state is initialized by randomizing delays and setting i = 0. @@ -848,19 +1000,22 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t r[3]) * scalar multiplication routine. */ typedef struct { - uint8_t i; - uint8_t delays[14]; + uint8_t i; + uint8_t delays[14]; } ecc_wait_state_t; + /* * Reset wait_state so that it's ready to be used. */ void ecc_wait_state_reset(ecc_wait_state_t *ws) { - if (ws == NULL) - return; - ws->i = 0; - mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays)); + if (ws == NULL) + return; + + ws->i = 0; + mbedtls_platform_random_buf(ws->delays, sizeof(ws->delays)); } + /* Computes result = left * right. Result must be 2 * num_words long. * * As a counter-measure against horizontal attacks, add noise by performing @@ -879,498 +1034,586 @@ void ecc_wait_state_reset(ecc_wait_state_t *ws) * Compared to the original uECC_vli_mult(), loose the num_words argument as we * know it's always 8. This saves a bit of code size and execution speed. */ -static void uECC_vli_mult_rnd(uECC_word_t *result, - const uECC_word_t *left, - const uECC_word_t *right, - ecc_wait_state_t *s) +static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, ecc_wait_state_t *s) { - uECC_word_t r[3] = { 0, 0, 0 }; - wordcount_t i, k; - const uint8_t num_words = NUM_ECC_WORDS; - /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ - uint8_t delays = s ? s->delays[s->i++] : 0; - uECC_word_t rr[3] = { 0, 0, 0 }; - volatile uECC_word_t rdummy; - /* Mimic start of next loop: k in [0, 3] */ - k = 0 + (delays & 0x03); - delays >>= 2; - /* k = 0 -> i in [1, 0] -> 0 extra muladd; + + uECC_word_t r[3] = { 0, 0, 0 }; + wordcount_t i, k; + const uint8_t num_words = NUM_ECC_WORDS; + + /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ + uint8_t delays = s ? s->delays[s->i++] : 0; + uECC_word_t rr[3] = { 0, 0, 0 }; + volatile uECC_word_t rdummy; + + /* Mimic start of next loop: k in [0, 3] */ + k = 0 + (delays & 0x03); + delays >>= 2; + /* k = 0 -> i in [1, 0] -> 0 extra muladd; * k = 3 -> i in [1, 3] -> 3 extra muladd */ - for (i = 1; i <= k; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - /* Compute each digit of result in sequence, maintaining the carries. */ - for (k = 0; k < num_words; ++k) { - for (i = 0; i <= k; ++i) { - muladd(left[i], right[k - i], r); - } - result[k] = r[0]; - r[0] = r[1]; - r[1] = r[2]; - r[2] = 0; - } - /* Mimic end of previous loop: k in [4, 7] */ - k = 4 + (delays & 0x03); - delays >>= 2; - /* k = 4 -> i in [5, 4] -> 0 extra muladd; + for (i = 1; i <= k; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], r); + } + + result[k] = r[0]; + r[0] = r[1]; + r[1] = r[2]; + r[2] = 0; + } + + /* Mimic end of previous loop: k in [4, 7] */ + k = 4 + (delays & 0x03); + delays >>= 2; + /* k = 4 -> i in [5, 4] -> 0 extra muladd; * k = 7 -> i in [5, 7] -> 3 extra muladd */ - for (i = 5; i <= k; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - /* Mimic start of next loop: k in [8, 11] */ - k = 11 - (delays & 0x03); - delays >>= 2; - /* k = 8 -> i in [5, 7] -> 3 extra muladd; + for (i = 5; i <= k; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + + /* Mimic start of next loop: k in [8, 11] */ + k = 11 - (delays & 0x03); + delays >>= 2; + /* k = 8 -> i in [5, 7] -> 3 extra muladd; * k = 11 -> i in [8, 7] -> 0 extra muladd */ - for (i = (k + 5) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - for (k = num_words; k < num_words * 2 - 1; ++k) { - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], r); - } - result[k] = r[0]; - r[0] = r[1]; - r[1] = r[2]; - r[2] = 0; - } - result[num_words * 2 - 1] = r[0]; - /* Mimic end of previous loop: k in [12, 15] */ - k = 15 - (delays & 0x03); - delays >>= 2; - /* k = 12 -> i in [5, 7] -> 3 extra muladd; + for (i = (k + 5) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + + for (k = num_words; k < num_words * 2 - 1; ++k) { + + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], r); + } + result[k] = r[0]; + r[0] = r[1]; + r[1] = r[2]; + r[2] = 0; + } + + result[num_words * 2 - 1] = r[0]; + + /* Mimic end of previous loop: k in [12, 15] */ + k = 15 - (delays & 0x03); + delays >>= 2; + /* k = 12 -> i in [5, 7] -> 3 extra muladd; * k = 15 -> i in [8, 7] -> 0 extra muladd */ - for (i = (k + 1) - num_words; i < num_words; ++i) { - muladd(left[i], right[k - i], rr); - } - rdummy = rr[0]; - rr[0] = rr[1]; - rr[1] = rr[2]; - rr[2] = 0; - /* avoid warning that rdummy is set but not used */ - (void)rdummy; + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], rr); + } + rdummy = rr[0]; + rr[0] = rr[1]; + rr[1] = rr[2]; + rr[2] = 0; + + /* avoid warning that rdummy is set but not used */ + (void) rdummy; } -void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) + +void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t carry = uECC_vli_add(result, left, right); - if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { - /* result > mod (result = mod + remainder), so subtract mod to get + uECC_word_t carry = uECC_vli_add(result, left, right); + if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ - uECC_vli_sub(result, result, mod); - } + uECC_vli_sub(result, result, mod); + } } -void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) + +void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t l_borrow = uECC_vli_sub(result, left, right); - if (l_borrow) { - /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + uECC_word_t l_borrow = uECC_vli_sub(result, left, right); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, * we can get the correct result from result + mod (with overflow). */ - uECC_vli_add(result, result, mod); - } + uECC_vli_add(result, result, mod); + } } + /* Computes result = product % mod, where product is 2N words long. */ /* Currently only designed to work for curve_p or curve_n. */ -void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, const uECC_word_t *mod) +void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, + const uECC_word_t *mod) { - uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; - uECC_word_t tmp[2 * NUM_ECC_WORDS]; - uECC_word_t *v[2] = { tmp, product }; - uECC_word_t index; - const wordcount_t num_words = NUM_ECC_WORDS; - /* Shift mod so its highest set bit is at the maximum position. */ - bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod); - wordcount_t word_shift = shift / uECC_WORD_BITS; - wordcount_t bit_shift = shift % uECC_WORD_BITS; - uECC_word_t carry = 0; - uECC_vli_clear(mod_multiple); - if (bit_shift > 0) { - for (index = 0; index < (uECC_word_t)num_words; ++index) { - mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; - carry = mod[index] >> (uECC_WORD_BITS - bit_shift); - } - } else { - uECC_vli_set(mod_multiple + word_shift, mod); - } - for (index = 1; shift >= 0; --shift) { - uECC_word_t borrow = 0; - wordcount_t i; - for (i = 0; i < num_words * 2; ++i) { - uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; - if (diff != v[index][i]) { - borrow = (diff > v[index][i]); - } - v[1 - index][i] = diff; - } - /* Swap the index if there was no borrow */ - index = !(index ^ borrow); - uECC_vli_rshift1(mod_multiple); - mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); - uECC_vli_rshift1(mod_multiple + num_words); - } - uECC_vli_set(result, v[index]); + uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; + uECC_word_t tmp[2 * NUM_ECC_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + const wordcount_t num_words = NUM_ECC_WORDS; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - + uECC_vli_numBits(mod); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod); + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + /* Swap the index if there was no borrow */ + index = !(index ^ borrow); + uECC_vli_rshift1(mod_multiple); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << + (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words); + } + uECC_vli_set(result, v[index]); } -void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, const uECC_word_t *mod) + +void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, const uECC_word_t *mod) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult_rnd(product, left, right, NULL); - uECC_vli_mmod(result, product, mod); + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult_rnd(product, left, right, NULL); + uECC_vli_mmod(result, product, mod); } -static void uECC_vli_modMult_rnd(uECC_word_t *result, - const uECC_word_t *left, - const uECC_word_t *right, - ecc_wait_state_t *s) + +static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, ecc_wait_state_t *s) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult_rnd(product, left, right, s); - vli_mmod_fast_secp256r1(result, product); + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult_rnd(product, left, right, s); + + vli_mmod_fast_secp256r1(result, product); } -void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right) + +void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right) { - uECC_vli_modMult_rnd(result, left, right, NULL); + uECC_vli_modMult_rnd(result, left, right, NULL); } + #define EVEN(vli) (!(vli[0] & 1)) -static void vli_modInv_update(uECC_word_t *uv, const uECC_word_t *mod) + +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod) { - uECC_word_t carry = 0; - if (!EVEN(uv)) { - carry = uECC_vli_add(uv, uv, mod); - } - uECC_vli_rshift1(uv); - if (carry) { - uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET; - } + + uECC_word_t carry = 0; + + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod); + } + uECC_vli_rshift1(uv); + if (carry) { + uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET; + } } -void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, const uECC_word_t *mod) + +void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, + const uECC_word_t *mod) { - uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; - uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; - cmpresult_t cmpResult; - if (uECC_vli_isZero(input)) { - uECC_vli_clear(result); - return; - } - uECC_vli_set(a, input); - uECC_vli_set(b, mod); - uECC_vli_clear(u); - u[0] = 1; - uECC_vli_clear(v); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { - if (EVEN(a)) { - uECC_vli_rshift1(a); - vli_modInv_update(u, mod); - } else if (EVEN(b)) { - uECC_vli_rshift1(b); - vli_modInv_update(v, mod); - } else if (cmpResult > 0) { - uECC_vli_sub(a, a, b); - uECC_vli_rshift1(a); - if (uECC_vli_cmp_unsafe(u, v) < 0) { - uECC_vli_add(u, u, mod); - } - uECC_vli_sub(u, u, v); - vli_modInv_update(u, mod); - } else { - uECC_vli_sub(b, b, a); - uECC_vli_rshift1(b); - if (uECC_vli_cmp_unsafe(v, u) < 0) { - uECC_vli_add(v, v, mod); - } - uECC_vli_sub(v, v, u); - vli_modInv_update(v, mod); - } - } - uECC_vli_set(result, u); + uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; + uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input)) { + uECC_vli_clear(result); + return; + } + + uECC_vli_set(a, input); + uECC_vli_set(b, mod); + uECC_vli_clear(u); + u[0] = 1; + uECC_vli_clear(v); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a); + vli_modInv_update(u, mod); + } else if (EVEN(b)) { + uECC_vli_rshift1(b); + vli_modInv_update(v, mod); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b); + uECC_vli_rshift1(a); + if (uECC_vli_cmp_unsafe(u, v) < 0) { + uECC_vli_add(u, u, mod); + } + uECC_vli_sub(u, u, v); + vli_modInv_update(u, mod); + } else { + uECC_vli_sub(b, b, a); + uECC_vli_rshift1(b); + if (uECC_vli_cmp_unsafe(v, u) < 0) { + uECC_vli_add(v, v, mod); + } + uECC_vli_sub(v, v, u); + vli_modInv_update(v, mod); + } + } + uECC_vli_set(result, u); } + /* ------ Point operations ------ */ -void double_jacobian_default(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *Z1) + +void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * Z1) { - /* t1 = X, t2 = Y, t3 = Z */ - uECC_word_t t4[NUM_ECC_WORDS]; - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - if (uECC_vli_isZero(Z1)) { - return; - } - uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */ - uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */ - uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */ - uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ - uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ - uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */ - uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */ - uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */ - uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ - uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */ - uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */ - if (uECC_vli_testBit(X1, 0)) { - uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p); - uECC_vli_rshift1(X1); - X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); - } else { - uECC_vli_rshift1(X1); - } - /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ - uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */ - uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */ - uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */ - uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ - /* t4 = B * (A - x3) - y1^4 = y3: */ - uECC_vli_modSub(t4, X1, t4, curve_p); - uECC_vli_set(X1, Z1); - uECC_vli_set(Z1, Y1); - uECC_vli_set(Y1, t4); + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[NUM_ECC_WORDS]; + uECC_word_t t5[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + + if (uECC_vli_isZero(Z1)) { + return; + } + + uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */ + uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ + uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ + + uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve_p); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve_p); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ + + uECC_vli_modAdd(Z1, X1, X1, curve_p); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve_p); + uECC_vli_rshift1(X1); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1); + } + + /* t1 = 3/2*(x1^2 - z1^4) = B */ + uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve_p); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ + /* t4 = B * (A - x3) - y1^4 = y3: */ + uECC_vli_modSub(t4, X1, t4, curve_p); + + uECC_vli_set(X1, Z1); + uECC_vli_set(Z1, Y1); + uECC_vli_set(Y1, t4); } + /* * @brief Computes x^3 + ax + b. result must not overlap x. * @param result OUT -- x^3 + ax + b * @param x IN -- value of x * @param curve IN -- elliptic curve */ -static void x_side_default(uECC_word_t *result, const uECC_word_t *x) +static void x_side_default(uECC_word_t *result, + const uECC_word_t *x) { - uECC_word_t _3[NUM_ECC_WORDS] = { 3 }; /* -a = 3 */ - uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ - uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */ - uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ - /* r = x^3 - 3x + b: */ - uECC_vli_modAdd(result, result, curve_b, curve_p); + uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ + + uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve_p); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ + /* r = x^3 - 3x + b: */ + uECC_vli_modAdd(result, result, curve_b, curve_p); } -void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product) + +void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) { - unsigned int tmp[NUM_ECC_WORDS]; - int carry; - /* t */ - uECC_vli_set(result, product); - /* s1 */ - tmp[0] = tmp[1] = tmp[2] = 0; - tmp[3] = product[11]; - tmp[4] = product[12]; - tmp[5] = product[13]; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry = uECC_vli_add(tmp, tmp, tmp); - carry += uECC_vli_add(result, result, tmp); - /* s2 */ - tmp[3] = product[12]; - tmp[4] = product[13]; - tmp[5] = product[14]; - tmp[6] = product[15]; - tmp[7] = 0; - carry += uECC_vli_add(tmp, tmp, tmp); - carry += uECC_vli_add(result, result, tmp); - /* s3 */ - tmp[0] = product[8]; - tmp[1] = product[9]; - tmp[2] = product[10]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[14]; - tmp[7] = product[15]; - carry += uECC_vli_add(result, result, tmp); - /* s4 */ - tmp[0] = product[9]; - tmp[1] = product[10]; - tmp[2] = product[11]; - tmp[3] = product[13]; - tmp[4] = product[14]; - tmp[5] = product[15]; - tmp[6] = product[13]; - tmp[7] = product[8]; - carry += uECC_vli_add(result, result, tmp); - /* d1 */ - tmp[0] = product[11]; - tmp[1] = product[12]; - tmp[2] = product[13]; - tmp[3] = tmp[4] = tmp[5] = 0; - tmp[6] = product[8]; - tmp[7] = product[10]; - carry -= uECC_vli_sub(result, result, tmp); - /* d2 */ - tmp[0] = product[12]; - tmp[1] = product[13]; - tmp[2] = product[14]; - tmp[3] = product[15]; - tmp[4] = tmp[5] = 0; - tmp[6] = product[9]; - tmp[7] = product[11]; - carry -= uECC_vli_sub(result, result, tmp); - /* d3 */ - tmp[0] = product[13]; - tmp[1] = product[14]; - tmp[2] = product[15]; - tmp[3] = product[8]; - tmp[4] = product[9]; - tmp[5] = product[10]; - tmp[6] = 0; - tmp[7] = product[12]; - carry -= uECC_vli_sub(result, result, tmp); - /* d4 */ - tmp[0] = product[14]; - tmp[1] = product[15]; - tmp[2] = 0; - tmp[3] = product[9]; - tmp[4] = product[10]; - tmp[5] = product[11]; - tmp[6] = 0; - tmp[7] = product[13]; - carry -= uECC_vli_sub(result, result, tmp); - if (carry < 0) { - do { - carry += uECC_vli_add(result, result, curve_p); - } while (carry < 0); - } else { - while (carry || uECC_vli_cmp_unsafe(curve_p, result) != 1) { - carry -= uECC_vli_sub(result, result, curve_p); - } - } + unsigned int tmp[NUM_ECC_WORDS]; + int carry; + + /* t */ + uECC_vli_set(result, product); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); + + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); + + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp); + + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp); + + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp); + + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp); + + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp); + + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_p); + } + while (carry < 0); + } else { + while (carry || + uECC_vli_cmp_unsafe(curve_p, result) != 1) { + carry -= uECC_vli_sub(result, result, curve_p); + } + } } + uECC_word_t EccPoint_isZero(const uECC_word_t *point) { - return uECC_vli_isZero(point); + return uECC_vli_isZero(point); } -void apply_z(uECC_word_t *X1, uECC_word_t *Y1, const uECC_word_t *const Z) + +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z) { - uECC_word_t t1[NUM_ECC_WORDS]; - uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */ - uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */ - uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */ - uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */ + uECC_word_t t1[NUM_ECC_WORDS]; + + uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */ } + /* P = (x1, y1) => 2P, (x2, y2) => P' */ -static void XYcZ_initial_double(uECC_word_t *X1, - uECC_word_t *Y1, - uECC_word_t *X2, - uECC_word_t *Y2, - const uECC_word_t *const initial_Z) +static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + const uECC_word_t * const initial_Z) { - uECC_word_t z[NUM_ECC_WORDS]; - if (initial_Z) { - uECC_vli_set(z, initial_Z); - } else { - uECC_vli_clear(z); - z[0] = 1; - } - uECC_vli_set(X2, X1); - uECC_vli_set(Y2, Y1); - apply_z(X1, Y1, z); - double_jacobian_default(X1, Y1, z); - apply_z(X2, Y2, z); + uECC_word_t z[NUM_ECC_WORDS]; + if (initial_Z) { + uECC_vli_set(z, initial_Z); + } else { + uECC_vli_clear(z); + z[0] = 1; + } + + uECC_vli_set(X2, X1); + uECC_vli_set(Y2, Y1); + + apply_z(X1, Y1, z); + double_jacobian_default(X1, Y1, z); + apply_z(X2, Y2, z); } -static void XYcZ_add_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2, ecc_wait_state_t *s) + +static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + ecc_wait_state_t *s) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ - uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ - uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ - uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ - uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */ - uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */ - uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */ - uECC_vli_set(X2, t5); + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + + uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ + uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve_p); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve_p); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve_p); /* t3 = C - B */ + uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve_p); /* t3 = B - x3 */ + uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y3 */ + + uECC_vli_set(X2, t5); } -void XYcZ_add(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2) + +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2) { - XYcZ_add_rnd(X1, Y1, X2, Y2, NULL); + XYcZ_add_rnd(X1, Y1, X2, Y2, NULL); } + /* Input P = (x1, y1, Z), Q = (x2, y2, Z) Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) or P => P - Q, Q => P + Q */ -static void XYcZ_addC_rnd(uECC_word_t *X1, uECC_word_t *Y1, uECC_word_t *X2, uECC_word_t *Y2, ecc_wait_state_t *s) +static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + ecc_wait_state_t *s) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - uECC_word_t t6[NUM_ECC_WORDS]; - uECC_word_t t7[NUM_ECC_WORDS]; - uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ - uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ - uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ - uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */ - uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ - uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */ - uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ - uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */ - uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */ - uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ - /* t4 = (y2 - y1)*(B - x3) - E = y3: */ - uECC_vli_modSub(Y2, Y2, Y1, curve_p); - uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ - uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */ - uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */ - uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ - /* t2 = (y2+y1)*(x3' - B) - E = y3': */ - uECC_vli_modSub(Y1, t6, Y1, curve_p); - uECC_vli_set(X1, t7); + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + uECC_word_t t6[NUM_ECC_WORDS]; + uECC_word_t t7[NUM_ECC_WORDS]; + + uECC_vli_modSub(t5, X2, X1, curve_p); /* t5 = x2 - x1 */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve_p); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); /* t4 = y2 - y1 */ + + uECC_vli_modSub(t6, X2, X1, curve_p); /* t6 = C - B */ + uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve_p); /* t6 = B + C */ + uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve_p); /* t3 = D - (B + C) = x3 */ + + uECC_vli_modSub(t7, X1, X2, curve_p); /* t7 = B - x3 */ + uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ + /* t4 = (y2 - y1)*(B - x3) - E = y3: */ + uECC_vli_modSub(Y2, Y2, Y1, curve_p); + + uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve_p); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve_p); /* t6 = x3' - B */ + uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ + /* t2 = (y2+y1)*(x3' - B) - E = y3': */ + uECC_vli_modSub(Y1, t6, Y1, curve_p); + + uECC_vli_set(X1, t7); } -static void EccPoint_mult(uECC_word_t *result, - const uECC_word_t *point, - const uECC_word_t *scalar, - const uECC_word_t *initial_Z) + +static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z) { - /* R0 and R1 */ - uECC_word_t Rx[2][NUM_ECC_WORDS]; - uECC_word_t Ry[2][NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - bitcount_t i; - uECC_word_t nb; - const wordcount_t num_words = NUM_ECC_WORDS; - const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */ - ecc_wait_state_t wait_state; - ecc_wait_state_t *const ws = g_rng_function ? &wait_state : NULL; - uECC_vli_set(Rx[1], point); - uECC_vli_set(Ry[1], point + num_words); - XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z); - for (i = num_bits - 2; i > 0; --i) { - ecc_wait_state_reset(ws); - nb = !uECC_vli_testBit(scalar, i); - XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); - XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); - } - ecc_wait_state_reset(ws); - nb = !uECC_vli_testBit(scalar, 0); - XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); - /* Find final 1/Z value. */ - uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */ - uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ - uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ - uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/ - /* yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, point + num_words); - /* Xb * yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, Rx[1 - nb]); - /* End 1/Z calculation */ - XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); - apply_z(Rx[0], Ry[0], z); - uECC_vli_set(result, Rx[0]); - uECC_vli_set(result + num_words, Ry[0]); + /* R0 and R1 */ + uECC_word_t Rx[2][NUM_ECC_WORDS]; + uECC_word_t Ry[2][NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + bitcount_t i; + uECC_word_t nb; + const wordcount_t num_words = NUM_ECC_WORDS; + const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */ + ecc_wait_state_t wait_state; + ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL; + + uECC_vli_set(Rx[1], point); + uECC_vli_set(Ry[1], point + num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z); + + for (i = num_bits - 2; i > 0; --i) { + ecc_wait_state_reset(ws); + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); + } + + ecc_wait_state_reset(ws); + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve_p); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0))*/ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words); + /* Xb * yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, Rx[1 - nb]); + /* End 1/Z calculation */ + + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); + apply_z(Rx[0], Ry[0], z); + + uECC_vli_set(result, Rx[0]); + uECC_vli_set(result + num_words, Ry[0]); } -static uECC_word_t regularize_k(const uECC_word_t *const k, uECC_word_t *k0, uECC_word_t *k1) + +static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, + uECC_word_t *k1) { - wordcount_t num_n_words = NUM_ECC_WORDS; - bitcount_t num_n_bits = NUM_ECC_BITS; - /* With our constant NUM_ECC_BITS and NUM_ECC_WORDS the + wordcount_t num_n_words = NUM_ECC_WORDS; + bitcount_t num_n_bits = NUM_ECC_BITS; + + /* With our constant NUM_ECC_BITS and NUM_ECC_WORDS the * check (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) always would have "false" result (256 < 256), * therefore Coverity warning may be detected. Removing of this line without changing the entire check will cause to * array overrun. @@ -1378,188 +1621,243 @@ static uECC_word_t regularize_k(const uECC_word_t *const k, uECC_word_t *k0, uEC * implementation and to allow upstreaming to other curves if required. * Coverity specific annotation may be added to silence warning if exists. */ - uECC_word_t carry = - uECC_vli_add(k0, k, curve_n) - || (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && uECC_vli_testBit(k0, num_n_bits)); - uECC_vli_add(k1, k0, curve_n); - return carry; + uECC_word_t carry = uECC_vli_add(k0, k, curve_n) || + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + + uECC_vli_add(k1, k0, curve_n); + + return carry; } -int EccPoint_mult_safer(uECC_word_t *result, const uECC_word_t *point, const uECC_word_t *scalar) + +int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t *k2[2] = { tmp, s }; - wordcount_t num_words = NUM_ECC_WORDS; - uECC_word_t carry; - uECC_word_t *initial_Z = 0; - int r = UECC_FAULT_DETECTED; - volatile int problem; - /* Protect against faults modifying curve paremeters in flash */ - problem = -1; - problem = uECC_check_curve_integrity(); - if (problem != 0) { - return UECC_FAULT_DETECTED; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - return UECC_FAULT_DETECTED; - } - /* Protects against invalid curve attacks */ - problem = -1; - problem = uECC_valid_point(point); - if (problem != 0) { - /* invalid input, can happen without fault */ - return UECC_FAILURE; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - /* failure on second check means fault, though */ - return UECC_FAULT_DETECTED; - } - /* Regularize the bitcount for the private key so that attackers cannot use a + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; + wordcount_t num_words = NUM_ECC_WORDS; + uECC_word_t carry; + uECC_word_t *initial_Z = 0; + int r = UECC_FAULT_DETECTED; + volatile int problem; + + /* Protect against faults modifying curve paremeters in flash */ + problem = -1; + problem = uECC_check_curve_integrity(); + if (problem != 0) { + return UECC_FAULT_DETECTED; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + return UECC_FAULT_DETECTED; + } + + /* Protects against invalid curve attacks */ + problem = -1; + problem = uECC_valid_point(point); + if (problem != 0) { + /* invalid input, can happen without fault */ + return UECC_FAILURE; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + /* failure on second check means fault, though */ + return UECC_FAULT_DETECTED; + } + + /* Regularize the bitcount for the private key so that attackers cannot use a * side channel attack to learn the number of leading zeros. */ - carry = regularize_k(scalar, tmp, s); - /* If an RNG function was specified, get a random initial Z value to + carry = regularize_k(scalar, tmp, s); + + /* If an RNG function was specified, get a random initial Z value to * protect against side-channel attacks such as Template SPA */ - if (g_rng_function) { - if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) { - r = UECC_FAILURE; - goto clear_and_out; - } - initial_Z = k2[carry]; - } - EccPoint_mult(result, point, k2[!carry], initial_Z); - /* Protect against fault injections that would make the resulting + if (g_rng_function) { + if (uECC_generate_random_int(k2[carry], curve_p, num_words) != UECC_SUCCESS) { + r = UECC_FAILURE; + goto clear_and_out; + } + initial_Z = k2[carry]; + } + + EccPoint_mult(result, point, k2[!carry], initial_Z); + + /* Protect against fault injections that would make the resulting * point not lie on the intended curve */ - problem = -1; - problem = uECC_valid_point(result); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - /* Protect against faults modifying curve paremeters in flash */ - problem = -1; - problem = uECC_check_curve_integrity(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - mbedtls_platform_random_delay(); - if (problem != 0) { - r = UECC_FAULT_DETECTED; - goto clear_and_out; - } - r = UECC_SUCCESS; + problem = -1; + problem = uECC_valid_point(result); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + + /* Protect against faults modifying curve paremeters in flash */ + problem = -1; + problem = uECC_check_curve_integrity(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + mbedtls_platform_random_delay(); + if (problem != 0) { + r = UECC_FAULT_DETECTED; + goto clear_and_out; + } + + r = UECC_SUCCESS; + clear_and_out: - /* erasing temporary buffer used to store secret: */ - mbedtls_platform_zeroize(k2, sizeof(k2)); - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - mbedtls_platform_zeroize(s, sizeof(s)); - return r; + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_zeroize(k2, sizeof(k2)); + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + mbedtls_platform_zeroize(s, sizeof(s)); + + return r; } -uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key) + +uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key) { - return EccPoint_mult_safer(result, curve_G, private_key); + return EccPoint_mult_safer(result, curve_G, private_key); } + /* Converts an integer in uECC native format to big-endian bytes. */ -void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const unsigned int *native) +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, + const unsigned int *native) { - wordcount_t i; - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); - } + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } } + /* Converts big-endian bytes to an integer in uECC native format. */ -void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, int num_bytes) +void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, + int num_bytes) { - wordcount_t i; - uECC_vli_clear(native); - for (i = 0; i < num_bytes; ++i) { - unsigned b = num_bytes - 1 - i; - native[b / uECC_WORD_SIZE] |= (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); - } + wordcount_t i; + uECC_vli_clear(native); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } } -int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, wordcount_t num_words) + +int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, + wordcount_t num_words) { - uECC_word_t mask = (uECC_word_t)-1; - uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top); - if (!g_rng_function) { - return UECC_FAILURE; - } - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random) && uECC_vli_cmp(top, random) == 1) { - return UECC_SUCCESS; - } - } - return UECC_FAILURE; + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top); + + if (!g_rng_function) { + return UECC_FAILURE; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE) != num_words * uECC_WORD_SIZE) { + return UECC_FAILURE; + } + random[num_words - 1] &= + mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random) && + uECC_vli_cmp(top, random) == 1) { + return UECC_SUCCESS; + } + } + return UECC_FAILURE; } + + int uECC_valid_point(const uECC_word_t *point) { - uECC_word_t tmp1[NUM_ECC_WORDS]; - uECC_word_t tmp2[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - volatile uECC_word_t diff = 0xffffffff; - /* The point at infinity is invalid. */ - if (EccPoint_isZero(point)) { - return -1; - } - /* x and y must be smaller than p. */ - if (uECC_vli_cmp_unsafe(curve_p, point) != 1 || uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) { - return -2; - } - uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words); - x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */ - /* Make sure that y^2 == x^3 + ax + b */ - diff = uECC_vli_equal(tmp1, tmp2); - if (diff == 0) { - mbedtls_platform_random_delay(); - if (diff == 0) { - return 0; - } - } - return -3; + uECC_word_t tmp1[NUM_ECC_WORDS]; + uECC_word_t tmp2[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + volatile uECC_word_t diff = 0xffffffff; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point)) { + return -1; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve_p, point) != 1 || + uECC_vli_cmp_unsafe(curve_p, point + num_words) != 1) { + return -2; + } + + uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words); + x_side_default(tmp2, point); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + diff = uECC_vli_equal(tmp1, tmp2); + if (diff == 0) { + mbedtls_platform_random_delay(); + if (diff == 0) { + return 0; + } + } + + return -3; } + int uECC_valid_public_key(const uint8_t *public_key) { - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); - uECC_vli_bytesToNative(_public + NUM_ECC_WORDS, public_key + NUM_ECC_BYTES, NUM_ECC_BYTES); - if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) { - return -4; - } - return uECC_valid_point(_public); + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); + uECC_vli_bytesToNative( + _public + NUM_ECC_WORDS, + public_key + NUM_ECC_BYTES, + NUM_ECC_BYTES); + + if (memcmp(_public, curve_G, NUM_ECC_WORDS * 2) == 0) { + return -4; + } + + return uECC_valid_point(_public); } + int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); - /* Make sure the private key is in the range [1, n-1]. */ - if (uECC_vli_isZero(_private)) { - return UECC_FAILURE; - } - if (uECC_vli_cmp(curve_n, _private) != 1) { - return UECC_FAILURE; - } - /* Compute public key. */ - ret = EccPoint_compute_public_key(_public, _private); - if (ret != UECC_SUCCESS) { - return ret; - } - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); - return ret; + int ret = UECC_FAULT_DETECTED; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + uECC_vli_bytesToNative( + _private, + private_key, + BITS_TO_BYTES(NUM_ECC_BITS)); + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private)) { + return UECC_FAILURE; + } + + if (uECC_vli_cmp(curve_n, _private) != 1) { + return UECC_FAILURE; + } + + /* Compute public key. */ + ret = EccPoint_compute_public_key(_public, _private); + if (ret != UECC_SUCCESS) { + return ret; + } + + uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); + uECC_vli_nativeToBytes( + public_key + + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); + + return ret; } -#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index 79ba08f8b1..5b992f0f35 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -1,8 +1,10 @@ /* ec_dh.c - TinyCrypt implementation of EC-DH */ + /* * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. * SPDX-License-Identifier: BSD-3-Clause */ + /* * Copyright (c) 2014, Kenneth MacKay * All rights reserved. @@ -27,6 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * @@ -56,99 +59,141 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif + #if defined(SL_MBEDTLS_USE_TINYCRYPT) -#include -#include #include #include -#include -int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, unsigned int *d) +#include +#include "mbedtls/platform_util.h" + +int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, + unsigned int *d) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - /* This function is designed for test purposes-only (such as validating NIST + int ret = UECC_FAULT_DETECTED; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + + /* This function is designed for test purposes-only (such as validating NIST * test vectors) as it uses a provided value for d instead of generating * it uniformly at random. */ - if (mbedtls_platform_memcpy(_private, d, NUM_ECC_BYTES) != _private) { - goto exit; - } - /* Computing public-key from private: */ - ret = EccPoint_compute_public_key(_public, _private); - if (ret != UECC_SUCCESS) { - goto exit; - } - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(NUM_ECC_BITS), _private); - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); + if( mbedtls_platform_memcpy (_private, d, NUM_ECC_BYTES) != _private ) + { + goto exit; + } + + /* Computing public-key from private: */ + ret = EccPoint_compute_public_key(_public, _private); + if (ret != UECC_SUCCESS) { + goto exit; + } + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(NUM_ECC_BITS), + _private); + uECC_vli_nativeToBytes(public_key, + NUM_ECC_BYTES, + _public); + uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, + NUM_ECC_BYTES, + _public + NUM_ECC_WORDS); + exit: - /* erasing temporary buffer used to store secret: */ - mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); - return ret; + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); + + return ret; } + int uECC_make_key(uint8_t *public_key, uint8_t *private_key) { - int ret = UECC_FAULT_DETECTED; - uECC_word_t _random[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t tries; - volatile uint8_t *public_key_dup = public_key; - volatile uint8_t *private_key_dup = private_key; - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _private uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function - || rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ - uECC_vli_mmod(_private, _random, curve_n); - /* Computing public-key from private: */ - ret = EccPoint_compute_public_key(_public, _private); - /* don't try again if a fault was detected */ - if (ret == UECC_FAULT_DETECTED) { - return ret; - } - if (ret == UECC_SUCCESS) { - /* Converting buffers to correct bit order: */ - uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(NUM_ECC_BITS), _private); - uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public); - uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS); - /* erasing temporary buffer that stored secret: */ - mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); - if (private_key == private_key_dup && public_key == public_key_dup) { - return UECC_SUCCESS; - } - /* Erase key in case of FI */ - mbedtls_platform_memset(public_key, 0, 2 * NUM_ECC_BYTES); - return UECC_FAULT_DETECTED; - } - } - return UECC_FAILURE; + int ret = UECC_FAULT_DETECTED; + uECC_word_t _random[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t tries; + volatile uint8_t *public_key_dup = public_key; + volatile uint8_t *private_key_dup = private_key; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _private uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE) != 2 * NUM_ECC_WORDS*uECC_WORD_SIZE) { + return UECC_FAILURE; + } + + /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ + uECC_vli_mmod(_private, _random, curve_n); + + /* Computing public-key from private: */ + ret = EccPoint_compute_public_key(_public, _private); + /* don't try again if a fault was detected */ + if (ret == UECC_FAULT_DETECTED) { + return ret; + } + if (ret == UECC_SUCCESS) { + + /* Converting buffers to correct bit order: */ + uECC_vli_nativeToBytes(private_key, + BITS_TO_BYTES(NUM_ECC_BITS), + _private); + uECC_vli_nativeToBytes(public_key, + NUM_ECC_BYTES, + _public); + uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES, + NUM_ECC_BYTES, + _public + NUM_ECC_WORDS); + + /* erasing temporary buffer that stored secret: */ + mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES); + + if (private_key == private_key_dup && public_key == public_key_dup) { + return UECC_SUCCESS; + } + /* Erase key in case of FI */ + mbedtls_platform_memset(public_key, 0, 2*NUM_ECC_BYTES); + return UECC_FAULT_DETECTED; + } + } + return UECC_FAILURE; } -int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uint8_t *secret) + +int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, + uint8_t *secret) { - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t _private[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - wordcount_t num_bytes = NUM_ECC_BYTES; - // int r = UECC_FAULT_DETECTED; - /* Converting buffers to correct bit order: */ - uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); - uECC_vli_bytesToNative(_public, public_key, num_bytes); - uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes); - int r = EccPoint_mult_safer(_public, _public, _private); - uECC_vli_nativeToBytes(secret, num_bytes, _public); - /* erasing temporary buffer used to store secret: */ - mbedtls_platform_zeroize(_private, sizeof(_private)); - - return UECC_FAULT_DETECTED; + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t _private[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + wordcount_t num_bytes = NUM_ECC_BYTES; + int r = UECC_FAULT_DETECTED; + + /* Converting buffers to correct bit order: */ + uECC_vli_bytesToNative(_private, + private_key, + BITS_TO_BYTES(NUM_ECC_BITS)); + uECC_vli_bytesToNative(_public, + public_key, + num_bytes); + uECC_vli_bytesToNative(_public + num_words, + public_key + num_bytes, + num_bytes); + + r = EccPoint_mult_safer(_public, _public, _private); + uECC_vli_nativeToBytes(secret, num_bytes, _public); + + /* erasing temporary buffer used to store secret: */ + if (_private == mbedtls_platform_zeroize(_private, sizeof(_private))) { + return r; + } + + return UECC_FAULT_DETECTED; } -#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ diff --git a/matter/mbedtls/tinycrypt/src/ecc_dsa.c b/matter/mbedtls/tinycrypt/src/ecc_dsa.c index ee9527ed08..1084ed5e52 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dsa.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dsa.c @@ -1,8 +1,10 @@ /* ec_dsa.c - TinyCrypt implementation of EC-DSA */ + /* * Copyright (c) 2019, Arm Limited (or its affiliates), All Rights Reserved. * SPDX-License-Identifier: BSD-3-Clause */ + /* Copyright (c) 2014, Kenneth MacKay * All rights reserved. * @@ -25,6 +27,7 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE.*/ + /* * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. * @@ -54,214 +57,262 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ + #if !defined(MBEDTLS_CONFIG_FILE) #include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif + #if defined(SL_MBEDTLS_USE_TINYCRYPT) -#include #include #include -#include -static void bits2int(uECC_word_t *native, const uint8_t *bits, unsigned bits_size) +#include "mbedtls/platform_util.h" + +static void bits2int(uECC_word_t *native, const uint8_t *bits, + unsigned bits_size) { - unsigned num_n_bytes = BITS_TO_BYTES(NUM_ECC_BITS); - if (bits_size > num_n_bytes) { - bits_size = num_n_bytes; - } - uECC_vli_clear(native); - uECC_vli_bytesToNative(native, bits, bits_size); + unsigned num_n_bytes = BITS_TO_BYTES(NUM_ECC_BITS); + + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + + uECC_vli_clear(native); + uECC_vli_bytesToNative(native, bits, bits_size); } -int uECC_sign_with_k(const uint8_t *private_key, - const uint8_t *message_hash, - unsigned hash_size, - uECC_word_t *k, - uint8_t *signature) + +int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uECC_word_t *k, uint8_t *signature) { - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t s[NUM_ECC_WORDS]; - uECC_word_t p[NUM_ECC_WORDS * 2]; - wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); - int r = UECC_FAILURE; - /* Make sure 0 < k < curve_n */ - if (uECC_vli_isZero(k) || uECC_vli_cmp(curve_n, k) != 1) { - return UECC_FAILURE; - } - r = EccPoint_mult_safer(p, curve_G, k); - if (r != UECC_SUCCESS) { - return r; - } - /* If an RNG function was specified, get a random number + + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t p[NUM_ECC_WORDS * 2]; + wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); + int r = UECC_FAILURE; + + + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k) || + uECC_vli_cmp(curve_n, k) != 1) { + return UECC_FAILURE; + } + + r = EccPoint_mult_safer(p, curve_G, k); + if (r != UECC_SUCCESS) { + return r; + } + + /* If an RNG function was specified, get a random number to prevent side channel analysis of k. */ - if (!uECC_get_rng()) { - uECC_vli_clear(tmp); - tmp[0] = 1; - } else if (uECC_generate_random_int(tmp, curve_n, num_n_words) != UECC_SUCCESS) { - return UECC_FAILURE; - } - /* Prevent side channel analysis of uECC_vli_modInv() to determine + if (!uECC_get_rng()) { + uECC_vli_clear(tmp); + tmp[0] = 1; + } + else if (uECC_generate_random_int(tmp, curve_n, num_n_words) != UECC_SUCCESS) { + return UECC_FAILURE; + } + + /* Prevent side channel analysis of uECC_vli_modInv() to determine bits of k / the private key by premultiplying by a random number */ - uECC_vli_modMult(k, k, tmp, curve_n); /* k' = rand * k */ - uECC_vli_modInv(k, k, curve_n); /* k = 1 / k' */ - uECC_vli_modMult(k, k, tmp, curve_n); /* k = 1 / k */ - uECC_vli_nativeToBytes(signature, NUM_ECC_BYTES, p); /* store r */ - /* tmp = d: */ - uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); - s[num_n_words - 1] = 0; - uECC_vli_set(s, p); - uECC_vli_modMult(s, tmp, s, curve_n); /* s = r*d */ - bits2int(tmp, message_hash, hash_size); - uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */ - uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */ - if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) { - return UECC_FAILURE; - } - uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s); - return r; + uECC_vli_modMult(k, k, tmp, curve_n); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve_n); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve_n); /* k = 1 / k */ + + uECC_vli_nativeToBytes(signature, NUM_ECC_BYTES, p); /* store r */ + + /* tmp = d: */ + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(NUM_ECC_BITS)); + + s[num_n_words - 1] = 0; + uECC_vli_set(s, p); + uECC_vli_modMult(s, tmp, s, curve_n); /* s = r*d */ + + bits2int(tmp, message_hash, hash_size); + uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) { + return UECC_FAILURE; + } + + uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s); + return r; } -int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, unsigned hash_size, uint8_t *signature) + +int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, + unsigned hash_size, uint8_t *signature) { - int r; - uECC_word_t _random[2 * NUM_ECC_WORDS]; - uECC_word_t k[NUM_ECC_WORDS]; - uECC_word_t tries; - volatile const uint8_t *private_key_dup = private_key; - volatile const uint8_t *message_hash_dup = message_hash; - volatile unsigned hash_size_dup = hash_size; - volatile uint8_t *signature_dup = signature; - for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { - /* Generating _random uniformly at random: */ - uECC_RNG_Function rng_function = uECC_get_rng(); - if (!rng_function - || rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) != 2 * NUM_ECC_WORDS * uECC_WORD_SIZE) { - return UECC_FAILURE; - } - // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): - uECC_vli_mmod(k, _random, curve_n); - r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature); - /* don't keep trying if a fault was detected */ - if (r == UECC_FAULT_DETECTED) { - mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); - return r; - } - if (r == UECC_SUCCESS) { - if (private_key_dup != private_key || message_hash_dup != message_hash || hash_size_dup != hash_size - || signature_dup != signature) { - mbedtls_platform_memset(signature, 0, 2 * NUM_ECC_BYTES); - return UECC_FAULT_DETECTED; - } - return UECC_SUCCESS; - } - /* else keep trying */ - } - return UECC_FAILURE; + int r; + uECC_word_t _random[2*NUM_ECC_WORDS]; + uECC_word_t k[NUM_ECC_WORDS]; + uECC_word_t tries; + volatile const uint8_t *private_key_dup = private_key; + volatile const uint8_t *message_hash_dup = message_hash; + volatile unsigned hash_size_dup = hash_size; + volatile uint8_t *signature_dup = signature; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + /* Generating _random uniformly at random: */ + uECC_RNG_Function rng_function = uECC_get_rng(); + if (!rng_function || + rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE) != 2*NUM_ECC_WORDS*uECC_WORD_SIZE) { + return UECC_FAILURE; + } + + // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): + uECC_vli_mmod(k, _random, curve_n); + + r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature); + /* don't keep trying if a fault was detected */ + if (r == UECC_FAULT_DETECTED) { + mbedtls_platform_memset(signature, 0, 2*NUM_ECC_BYTES); + return r; + } + if (r == UECC_SUCCESS) { + if (private_key_dup != private_key || message_hash_dup != message_hash || + hash_size_dup != hash_size || signature_dup != signature) { + mbedtls_platform_memset(signature, 0, 2*NUM_ECC_BYTES); + return UECC_FAULT_DETECTED; + } + return UECC_SUCCESS; + } + /* else keep trying */ + } + return UECC_FAILURE; } + static bitcount_t smax(bitcount_t a, bitcount_t b) { - return (a > b ? a : b); + return (a > b ? a : b); } -int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, unsigned hash_size, const uint8_t *signature) + +int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, + unsigned hash_size, const uint8_t *signature) { - uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; - uECC_word_t z[NUM_ECC_WORDS]; - uECC_word_t sum[NUM_ECC_WORDS * 2]; - uECC_word_t rx[NUM_ECC_WORDS]; - uECC_word_t ry[NUM_ECC_WORDS]; - uECC_word_t tx[NUM_ECC_WORDS]; - uECC_word_t ty[NUM_ECC_WORDS]; - uECC_word_t tz[NUM_ECC_WORDS]; - const uECC_word_t *points[4]; - const uECC_word_t *point; - bitcount_t num_bits; - bitcount_t i; - bitcount_t flow_control; - volatile uECC_word_t diff; - uECC_word_t _public[NUM_ECC_WORDS * 2]; - uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; - wordcount_t num_words = NUM_ECC_WORDS; - wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); - rx[num_n_words - 1] = 0; - r[num_n_words - 1] = 0; - s[num_n_words - 1] = 0; - flow_control = 1; - uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); - uECC_vli_bytesToNative(_public + num_words, public_key + NUM_ECC_BYTES, NUM_ECC_BYTES); - uECC_vli_bytesToNative(r, signature, NUM_ECC_BYTES); - uECC_vli_bytesToNative(s, signature + NUM_ECC_BYTES, NUM_ECC_BYTES); - /* r, s must not be 0. */ - if (uECC_vli_isZero(r) || uECC_vli_isZero(s)) { - return UECC_FAILURE; - } - /* r, s must be < n. */ - if (uECC_vli_cmp_unsafe(curve_n, r) != 1 || uECC_vli_cmp_unsafe(curve_n, s) != 1) { - return UECC_FAILURE; - } - flow_control++; - /* Calculate u1 and u2. */ - uECC_vli_modInv(z, s, curve_n); /* z = 1/s */ - u1[num_n_words - 1] = 0; - bits2int(u1, message_hash, hash_size); - uECC_vli_modMult(u1, u1, z, curve_n); /* u1 = e/s */ - uECC_vli_modMult(u2, r, z, curve_n); /* u2 = r/s */ - /* Calculate sum = G + Q. */ - uECC_vli_set(sum, _public); - uECC_vli_set(sum + num_words, _public + num_words); - uECC_vli_set(tx, curve_G); - uECC_vli_set(ty, curve_G + num_words); - uECC_vli_modSub(z, sum, tx, curve_p); /* z = x2 - x1 */ - XYcZ_add(tx, ty, sum, sum + num_words); - uECC_vli_modInv(z, z, curve_p); /* z = 1/z */ - apply_z(sum, sum + num_words, z); - flow_control++; - /* Use Shamir's trick to calculate u1*G + u2*Q */ - points[0] = 0; - points[1] = curve_G; - points[2] = _public; - points[3] = sum; - num_bits = smax(uECC_vli_numBits(u1), uECC_vli_numBits(u2)); - point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; - uECC_vli_set(rx, point); - uECC_vli_set(ry, point + num_words); - uECC_vli_clear(z); - z[0] = 1; - flow_control++; - for (i = num_bits - 2; i >= 0; --i) { - uECC_word_t index; - double_jacobian_default(rx, ry, z); - index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); - point = points[index]; - if (point) { - uECC_vli_set(tx, point); - uECC_vli_set(ty, point + num_words); - apply_z(tx, ty, z); - uECC_vli_modSub(tz, rx, tx, curve_p); /* Z = x2 - x1 */ - XYcZ_add(tx, ty, rx, ry); - uECC_vli_modMult_fast(z, z, tz); - } - flow_control++; - } - uECC_vli_modInv(z, z, curve_p); /* Z = 1/Z */ - apply_z(rx, ry, z); - flow_control++; - /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve_n, rx) != 1) { - uECC_vli_sub(rx, rx, curve_n); - } - /* Accept only if v == r. */ - diff = uECC_vli_equal(rx, r); - if (diff == 0) { - flow_control++; - mbedtls_platform_random_delay(); - /* Re-check the condition and test if the control flow is as expected. + + uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS]; + uECC_word_t z[NUM_ECC_WORDS]; + uECC_word_t sum[NUM_ECC_WORDS * 2]; + uECC_word_t rx[NUM_ECC_WORDS]; + uECC_word_t ry[NUM_ECC_WORDS]; + uECC_word_t tx[NUM_ECC_WORDS]; + uECC_word_t ty[NUM_ECC_WORDS]; + uECC_word_t tz[NUM_ECC_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; + bitcount_t flow_control; + volatile uECC_word_t diff; + + uECC_word_t _public[NUM_ECC_WORDS * 2]; + uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS]; + wordcount_t num_words = NUM_ECC_WORDS; + wordcount_t num_n_words = BITS_TO_WORDS(NUM_ECC_BITS); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + flow_control = 1; + + uECC_vli_bytesToNative(_public, public_key, NUM_ECC_BYTES); + uECC_vli_bytesToNative(_public + num_words, public_key + NUM_ECC_BYTES, + NUM_ECC_BYTES); + uECC_vli_bytesToNative(r, signature, NUM_ECC_BYTES); + uECC_vli_bytesToNative(s, signature + NUM_ECC_BYTES, NUM_ECC_BYTES); + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r) || uECC_vli_isZero(s)) { + return UECC_FAILURE; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve_n, r) != 1 || + uECC_vli_cmp_unsafe(curve_n, s) != 1) { + return UECC_FAILURE; + } + + flow_control++; + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve_n); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size); + uECC_vli_modMult(u1, u1, z, curve_n); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve_n); /* u2 = r/s */ + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public); + uECC_vli_set(sum + num_words, _public + num_words); + uECC_vli_set(tx, curve_G); + uECC_vli_set(ty, curve_G + num_words); + uECC_vli_modSub(z, sum, tx, curve_p); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words); + uECC_vli_modInv(z, z, curve_p); /* z = 1/z */ + apply_z(sum, sum + num_words, z); + + flow_control++; + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve_G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1), + uECC_vli_numBits(u2)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point); + uECC_vli_set(ry, point + num_words); + uECC_vli_clear(z); + z[0] = 1; + flow_control++; + + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + double_jacobian_default(rx, ry, z); + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point); + uECC_vli_set(ty, point + num_words); + apply_z(tx, ty, z); + uECC_vli_modSub(tz, rx, tx, curve_p); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry); + uECC_vli_modMult_fast(z, z, tz); + } + flow_control++; + } + + uECC_vli_modInv(z, z, curve_p); /* Z = 1/Z */ + apply_z(rx, ry, z); + flow_control++; + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve_n, rx) != 1) { + uECC_vli_sub(rx, rx, curve_n); + } + + /* Accept only if v == r. */ + diff = uECC_vli_equal(rx, r); + if (diff == 0) { + flow_control++; + mbedtls_platform_random_delay(); + + /* Re-check the condition and test if the control flow is as expected. * 1 (base value) + num_bits - 1 (from the loop) + 5 incrementations. */ - if (diff == 0 && flow_control == (num_bits + 5)) { - return UECC_SUCCESS; - } else { - return UECC_FAULT_DETECTED; - } - } - return UECC_FAILURE; + if (diff == 0 && flow_control == (num_bits + 5)) { + return UECC_SUCCESS; + } + else { + return UECC_FAULT_DETECTED; + } + } + + return UECC_FAILURE; } -#endif /* SL_MBEDTLS_USE_TINYCRYPT */ \ No newline at end of file +#endif /* SL_MBEDTLS_USE_TINYCRYPT */ diff --git a/matter/mbedtls/tinycrypt/src/oid.c b/matter/mbedtls/tinycrypt/src/oid.c deleted file mode 100644 index d139a6d0de..0000000000 --- a/matter/mbedtls/tinycrypt/src/oid.c +++ /dev/null @@ -1,1166 +0,0 @@ -/** - * \file oid.c - * - * \brief Object Identifier (OID) database - * - * 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. - */ - -#include "common.h" - -#if defined(MBEDTLS_OID_C) - -#include "mbedtls/oid.h" -#include "mbedtls/rsa.h" -#include "mbedtls/error.h" -#include "mbedtls/pk.h" - -#include -#include - -#include "mbedtls/platform.h" - -/* - * Macro to automatically add the size of #define'd OIDs - */ -#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) - -/* - * Macro to generate mbedtls_oid_descriptor_t - */ -#if !defined(MBEDTLS_X509_REMOVE_INFO) -#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } -#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } -#else -#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } -#define NULL_OID_DESCRIPTOR { NULL, 0 } -#endif - -/* - * Macro to generate an internal function for oid_XXX_from_asn1() (used by - * the other functions) - */ -#define FN_OID_TYPED_FROM_ASN1(TYPE_T, NAME, LIST) \ - static const TYPE_T *oid_ ## NAME ## _from_asn1( \ - const mbedtls_asn1_buf *oid) \ - { \ - const TYPE_T *p = (LIST); \ - const mbedtls_oid_descriptor_t *cur = \ - (const mbedtls_oid_descriptor_t *) p; \ - if (p == NULL || oid == NULL) return NULL; \ - while (cur->asn1 != NULL) { \ - if (cur->asn1_len == oid->len && \ - memcmp(cur->asn1, oid->p, oid->len) == 0) { \ - return p; \ - } \ - p++; \ - cur = (const mbedtls_oid_descriptor_t *) p; \ - } \ - return NULL; \ - } - -#if !defined(MBEDTLS_X509_REMOVE_INFO) -/* - * Macro to generate a function for retrieving a single attribute from the - * descriptor of an mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ - { \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ - if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ - *ATTR1 = data->descriptor.ATTR1; \ - return 0; \ - } -#endif /* MBEDTLS_X509_REMOVE_INFO */ - -/* - * Macro to generate a function for retrieving a single attribute from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1) \ - { \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ - if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ - *ATTR1 = data->ATTR1; \ - return 0; \ - } - -/* - * Macro to generate a function for retrieving two attributes from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ - int FN_NAME(const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ - ATTR2_TYPE * ATTR2) \ - { \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1(oid); \ - if (data == NULL) return MBEDTLS_ERR_OID_NOT_FOUND; \ - *(ATTR1) = data->ATTR1; \ - *(ATTR2) = data->ATTR2; \ - return 0; \ - } - -/* - * Macro to generate a function for retrieving the OID based on a single - * attribute from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ - int FN_NAME(ATTR1_TYPE ATTR1, const char **oid, size_t *olen) \ - { \ - const TYPE_T *cur = (LIST); \ - while (cur->descriptor.asn1 != NULL) { \ - if (cur->ATTR1 == (ATTR1)) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return 0; \ - } \ - cur++; \ - } \ - return MBEDTLS_ERR_OID_NOT_FOUND; \ - } - -/* - * Macro to generate a function for retrieving the OID based on two - * attributes from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ - int FN_NAME(ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid, \ - size_t *olen) \ - { \ - const TYPE_T *cur = (LIST); \ - while (cur->descriptor.asn1 != NULL) { \ - if (cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2)) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return 0; \ - } \ - cur++; \ - } \ - return MBEDTLS_ERR_OID_NOT_FOUND; \ - } - -/* - * For X520 attribute types - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - const char *short_name; -} oid_x520_attr_t; - -static const oid_x520_attr_t oid_x520_attr_type[] = -{ - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name"), - "CN", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country"), - "C", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality"), - "L", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_STATE, "id-at-state", "State"), - "ST", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_ORGANIZATION, "id-at-organizationName", - "Organization"), - "O", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit"), - "OU", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS9_EMAIL, - "emailAddress", - "E-mail address"), - "emailAddress", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_SERIAL_NUMBER, - "id-at-serialNumber", - "Serial number"), - "serialNumber", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_ADDRESS, - "id-at-postalAddress", - "Postal address"), - "postalAddress", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code"), - "postalCode", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname"), - "SN", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name"), - "GN", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials"), - "initials", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_GENERATION_QUALIFIER, - "id-at-generationQualifier", - "Generation qualifier"), - "generationQualifier", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_TITLE, "id-at-title", "Title"), - "title", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_DN_QUALIFIER, - "id-at-dnQualifier", - "Distinguished Name qualifier"), - "dnQualifier", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym"), - "pseudonym", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_UID, "id-uid", "User Id"), - "uid", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_DOMAIN_COMPONENT, - "id-domainComponent", - "Domain component"), - "DC", - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, - "id-at-uniqueIdentifier", - "Unique Identifier"), - "uniqueIdentifier", - }, - { - NULL_OID_DESCRIPTOR, - NULL, - } -}; - -FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) -FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, - oid_x520_attr_t, - x520_attr, - const char *, - short_name) - -/* - * For X509 extensions - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - int ext_type; -} oid_x509_ext_t; - -static const oid_x509_ext_t oid_x509_ext[] = -{ - { - OID_DESCRIPTOR(MBEDTLS_OID_BASIC_CONSTRAINTS, - "id-ce-basicConstraints", - "Basic Constraints"), - MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage"), - MBEDTLS_OID_X509_EXT_KEY_USAGE, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_EXTENDED_KEY_USAGE, - "id-ce-extKeyUsage", - "Extended Key Usage"), - MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_ALT_NAME, - "id-ce-subjectAltName", - "Subject Alt Name"), - MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_NS_CERT_TYPE, - "id-netscape-certtype", - "Netscape Certificate Type"), - MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_CERTIFICATE_POLICIES, - "id-ce-certificatePolicies", - "Certificate Policies"), - MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, - "id-ce-subjectKeyIdentifier", - "Subject Key Identifier"), - MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, - "id-ce-authorityKeyIdentifier", - "Authority Key Identifier"), - MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, - }, - { - NULL_OID_DESCRIPTOR, - 0, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) -FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) - -#if !defined(MBEDTLS_X509_REMOVE_INFO) -static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = -{ - OID_DESCRIPTOR(MBEDTLS_OID_SERVER_AUTH, - "id-kp-serverAuth", - "TLS Web Server Authentication"), - OID_DESCRIPTOR(MBEDTLS_OID_CLIENT_AUTH, - "id-kp-clientAuth", - "TLS Web Client Authentication"), - OID_DESCRIPTOR(MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing"), - OID_DESCRIPTOR(MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection"), - OID_DESCRIPTOR(MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping"), - OID_DESCRIPTOR(MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing"), - OID_DESCRIPTOR(MBEDTLS_OID_WISUN_FAN, - "id-kp-wisun-fan-device", - "Wi-SUN Alliance Field Area Network (FAN)"), - NULL_OID_DESCRIPTOR, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) -FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, - mbedtls_oid_descriptor_t, - ext_key_usage, - const char *, - description) - -static const mbedtls_oid_descriptor_t oid_certificate_policies[] = -{ - OID_DESCRIPTOR(MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy"), - NULL_OID_DESCRIPTOR, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) -FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, - mbedtls_oid_descriptor_t, - certificate_policies, - const char *, - description) -#endif /* MBEDTLS_X509_REMOVE_INFO */ - -/* - * For SignatureAlgorithmIdentifier - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_pk_type_t pk_alg; -} oid_sig_alg_t; - -static const oid_sig_alg_t oid_sig_alg[] = -{ -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_MD_CAN_MD5) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5"), - MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_MD5 */ -#if defined(MBEDTLS_MD_CAN_SHA1) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1"), - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_MD_CAN_SHA224) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", - "RSA with SHA-224"), - MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA224 */ -#if defined(MBEDTLS_MD_CAN_SHA256) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", - "RSA with SHA-256"), - MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_MD_CAN_SHA384) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", - "RSA with SHA-384"), - MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_MD_CAN_SHA512) - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", - "RSA with SHA-512"), - MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA512 */ -#if defined(MBEDTLS_MD_CAN_SHA1) - { - OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1"), - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA1 */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) -#if defined(MBEDTLS_MD_CAN_SHA1) - { - OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1"), - MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_MD_CAN_SHA224) - { - OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224"), - MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA256) - { - OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256"), - MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_MD_CAN_SHA384) - { - OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384"), - MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_MD_CAN_SHA512) - { - OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512"), - MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_MD_CAN_SHA512 */ -#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ -#if defined(MBEDTLS_RSA_C) - { - OID_DESCRIPTOR(MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS"), - MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, - }, -#endif /* MBEDTLS_RSA_C */ - { - NULL_OID_DESCRIPTOR, - MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) - -#if !defined(MBEDTLS_X509_REMOVE_INFO) -FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, - oid_sig_alg_t, - sig_alg, - const char *, - description) -#endif - -FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, - oid_sig_alg_t, - sig_alg, - mbedtls_md_type_t, - md_alg, - mbedtls_pk_type_t, - pk_alg) -FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, - oid_sig_alg_t, - oid_sig_alg, - mbedtls_pk_type_t, - pk_alg, - mbedtls_md_type_t, - md_alg) - -/* - * For PublicKeyInfo (PKCS1, RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_pk_type_t pk_alg; -} oid_pk_alg_t; - -static const oid_pk_alg_t oid_pk_alg[] = -{ - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA"), - MBEDTLS_PK_RSA, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key"), - MBEDTLS_PK_ECKEY, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH"), - MBEDTLS_PK_ECKEY_DH, - }, - { - NULL_OID_DESCRIPTOR, - MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, - oid_pk_alg_t, - oid_pk_alg, - mbedtls_pk_type_t, - pk_alg) - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -/* - * For elliptic curves that use namedCurve inside ECParams (RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_ecp_group_id grp_id; -} oid_ecp_grp_t; - -static const oid_ecp_grp_t oid_ecp_grp[] = -{ -#if defined(MBEDTLS_ECP_HAVE_SECP192R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1"), - MBEDTLS_ECP_DP_SECP192R1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP192R1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP224R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1"), - MBEDTLS_ECP_DP_SECP224R1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP224R1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP256R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1"), - MBEDTLS_ECP_DP_SECP256R1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP256R1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP384R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1"), - MBEDTLS_ECP_DP_SECP384R1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP384R1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP521R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1"), - MBEDTLS_ECP_DP_SECP521R1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP521R1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP192K1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1"), - MBEDTLS_ECP_DP_SECP192K1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP192K1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP224K1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1"), - MBEDTLS_ECP_DP_SECP224K1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP224K1 */ -#if defined(MBEDTLS_ECP_HAVE_SECP256K1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1"), - MBEDTLS_ECP_DP_SECP256K1, - }, -#endif /* MBEDTLS_ECP_HAVE_SECP256K1 */ -#if defined(MBEDTLS_ECP_HAVE_BP256R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1", "brainpool256r1"), - MBEDTLS_ECP_DP_BP256R1, - }, -#endif /* MBEDTLS_ECP_HAVE_BP256R1 */ -#if defined(MBEDTLS_ECP_HAVE_BP384R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1", "brainpool384r1"), - MBEDTLS_ECP_DP_BP384R1, - }, -#endif /* MBEDTLS_ECP_HAVE_BP384R1 */ -#if defined(MBEDTLS_ECP_HAVE_BP512R1) - { - OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1", "brainpool512r1"), - MBEDTLS_ECP_DP_BP512R1, - }, -#endif /* MBEDTLS_ECP_HAVE_BP512R1 */ - { - NULL_OID_DESCRIPTOR, - MBEDTLS_ECP_DP_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, - oid_ecp_grp_t, - oid_ecp_grp, - mbedtls_ecp_group_id, - grp_id) - -/* - * For Elliptic Curve algorithms that are directly - * encoded in the AlgorithmIdentifier (RFC 8410) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_ecp_group_id grp_id; -} oid_ecp_grp_algid_t; - -static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] = -{ -#if defined(MBEDTLS_ECP_HAVE_CURVE25519) - { - OID_DESCRIPTOR(MBEDTLS_OID_X25519, "X25519", "X25519"), - MBEDTLS_ECP_DP_CURVE25519, - }, -#endif /* MBEDTLS_ECP_HAVE_CURVE25519 */ -#if defined(MBEDTLS_ECP_HAVE_CURVE448) - { - OID_DESCRIPTOR(MBEDTLS_OID_X448, "X448", "X448"), - MBEDTLS_ECP_DP_CURVE448, - }, -#endif /* MBEDTLS_ECP_HAVE_CURVE448 */ - { - NULL_OID_DESCRIPTOR, - MBEDTLS_ECP_DP_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid, - oid_ecp_grp_algid_t, - grp_id_algid, - mbedtls_ecp_group_id, - grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid, - oid_ecp_grp_algid_t, - oid_ecp_grp_algid, - mbedtls_ecp_group_id, - grp_id) -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_CIPHER_C) -/* - * For PKCS#5 PBES2 encryption algorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_cipher_type_t cipher_alg; -} oid_cipher_alg_t; - -static const oid_cipher_alg_t oid_cipher_alg[] = -{ - { - OID_DESCRIPTOR(MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC"), - MBEDTLS_CIPHER_DES_CBC, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"), - MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - NULL_OID_DESCRIPTOR, - MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, - oid_cipher_alg_t, - cipher_alg, - mbedtls_cipher_type_t, - cipher_alg) -#endif /* MBEDTLS_CIPHER_C */ - -/* - * For digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; -} oid_md_alg_t; - -static const oid_md_alg_t oid_md_alg[] = -{ -#if defined(MBEDTLS_MD_CAN_MD5) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5"), - MBEDTLS_MD_MD5, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA1) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1"), - MBEDTLS_MD_SHA1, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA224) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224"), - MBEDTLS_MD_SHA224, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA256) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256"), - MBEDTLS_MD_SHA256, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA384) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384"), - MBEDTLS_MD_SHA384, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA512) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512"), - MBEDTLS_MD_SHA512, - }, -#endif -#if defined(MBEDTLS_MD_CAN_RIPEMD160) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"), - MBEDTLS_MD_RIPEMD160, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA3_224) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224, "id-sha3-224", "SHA-3-224"), - MBEDTLS_MD_SHA3_224, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA3_256) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256, "id-sha3-256", "SHA-3-256"), - MBEDTLS_MD_SHA3_256, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA3_384) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384, "id-sha3-384", "SHA-3-384"), - MBEDTLS_MD_SHA3_384, - }, -#endif -#if defined(MBEDTLS_MD_CAN_SHA3_512) - { - OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512, "id-sha3-512", "SHA-3-512"), - MBEDTLS_MD_SHA3_512, - }, -#endif - { - NULL_OID_DESCRIPTOR, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, - oid_md_alg_t, - oid_md_alg, - mbedtls_md_type_t, - md_alg) - -/* - * For HMAC digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_hmac; -} oid_md_hmac_t; - -static const oid_md_hmac_t oid_md_hmac[] = -{ -#if defined(MBEDTLS_MD_CAN_SHA1) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1"), - MBEDTLS_MD_SHA1, - }, -#endif /* MBEDTLS_MD_CAN_SHA1 */ -#if defined(MBEDTLS_MD_CAN_SHA224) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224"), - MBEDTLS_MD_SHA224, - }, -#endif /* MBEDTLS_MD_CAN_SHA224 */ -#if defined(MBEDTLS_MD_CAN_SHA256) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256"), - MBEDTLS_MD_SHA256, - }, -#endif /* MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_MD_CAN_SHA384) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384"), - MBEDTLS_MD_SHA384, - }, -#endif /* MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_MD_CAN_SHA512) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512"), - MBEDTLS_MD_SHA512, - }, -#endif /* MBEDTLS_MD_CAN_SHA512 */ -#if defined(MBEDTLS_MD_CAN_SHA3_224) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224, "hmacSHA3-224", "HMAC-SHA3-224"), - MBEDTLS_MD_SHA3_224, - }, -#endif /* MBEDTLS_MD_CAN_SHA3_224 */ -#if defined(MBEDTLS_MD_CAN_SHA3_256) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256, "hmacSHA3-256", "HMAC-SHA3-256"), - MBEDTLS_MD_SHA3_256, - }, -#endif /* MBEDTLS_MD_CAN_SHA3_256 */ -#if defined(MBEDTLS_MD_CAN_SHA3_384) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384, "hmacSHA3-384", "HMAC-SHA3-384"), - MBEDTLS_MD_SHA3_384, - }, -#endif /* MBEDTLS_MD_CAN_SHA3_384 */ -#if defined(MBEDTLS_MD_CAN_SHA3_512) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512, "hmacSHA3-512", "HMAC-SHA3-512"), - MBEDTLS_MD_SHA3_512, - }, -#endif /* MBEDTLS_MD_CAN_SHA3_512 */ -#if defined(MBEDTLS_MD_CAN_RIPEMD160) - { - OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160, "hmacRIPEMD160", "HMAC-RIPEMD160"), - MBEDTLS_MD_RIPEMD160, - }, -#endif /* MBEDTLS_MD_CAN_RIPEMD160 */ - { - NULL_OID_DESCRIPTOR, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) - -#if defined(MBEDTLS_PKCS12_C) -/* - * For PKCS#12 PBEs - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_cipher_type_t cipher_alg; -} oid_pkcs12_pbe_alg_t; - -static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = -{ - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, - "pbeWithSHAAnd3-KeyTripleDES-CBC", - "PBE with SHA1 and 3-Key 3DES"), - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - OID_DESCRIPTOR(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, - "pbeWithSHAAnd2-KeyTripleDES-CBC", - "PBE with SHA1 and 2-Key 3DES"), - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, - }, - { - NULL_OID_DESCRIPTOR, - MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) -FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, - oid_pkcs12_pbe_alg_t, - pkcs12_pbe_alg, - mbedtls_md_type_t, - md_alg, - mbedtls_cipher_type_t, - cipher_alg) -#endif /* MBEDTLS_PKCS12_C */ - -/* Return the x.y.z.... style numeric string for the given OID */ -int mbedtls_oid_get_numeric_string(char *buf, size_t size, - const mbedtls_asn1_buf *oid) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - char *p = buf; - size_t n = size; - unsigned int value = 0; - - if (size > INT_MAX) { - /* Avoid overflow computing return value */ - return MBEDTLS_ERR_ASN1_INVALID_LENGTH; - } - - if (oid->len <= 0) { - /* OID must not be empty */ - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - for (size_t i = 0; i < oid->len; i++) { - /* Prevent overflow in value. */ - if (value > (UINT_MAX >> 7)) { - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } - if ((value == 0) && ((oid->p[i]) == 0x80)) { - /* Overlong encoding is not allowed */ - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } - - value <<= 7; - value |= oid->p[i] & 0x7F; - - if (!(oid->p[i] & 0x80)) { - /* Last byte */ - if (n == size) { - int component1; - unsigned int component2; - /* First subidentifier contains first two OID components */ - if (value >= 80) { - component1 = '2'; - component2 = value - 80; - } else if (value >= 40) { - component1 = '1'; - component2 = value - 40; - } else { - component1 = '0'; - component2 = value; - } - ret = mbedtls_snprintf(p, n, "%c.%u", component1, component2); - } else { - ret = mbedtls_snprintf(p, n, ".%u", value); - } - if (ret < 2 || (size_t) ret >= n) { - return MBEDTLS_ERR_OID_BUF_TOO_SMALL; - } - n -= (size_t) ret; - p += ret; - value = 0; - } - } - - if (value != 0) { - /* Unterminated subidentifier */ - return MBEDTLS_ERR_ASN1_OUT_OF_DATA; - } - - return (int) (size - n); -} - -static int oid_parse_number(unsigned int *num, const char **p, const char *bound) -{ - int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - - *num = 0; - - while (*p < bound && **p >= '0' && **p <= '9') { - ret = 0; - if (*num > (UINT_MAX / 10)) { - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } - *num *= 10; - *num += **p - '0'; - (*p)++; - } - return ret; -} - -static size_t oid_subidentifier_num_bytes(unsigned int value) -{ - size_t num_bytes = 0; - - do { - value >>= 7; - num_bytes++; - } while (value != 0); - - return num_bytes; -} - -static int oid_subidentifier_encode_into(unsigned char **p, - unsigned char *bound, - unsigned int value) -{ - size_t num_bytes = oid_subidentifier_num_bytes(value); - - if ((size_t) (bound - *p) < num_bytes) { - return MBEDTLS_ERR_OID_BUF_TOO_SMALL; - } - (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f); - value >>= 7; - - for (size_t i = 2; i <= num_bytes; i++) { - (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f); - value >>= 7; - } - *p += num_bytes; - - return 0; -} - -/* Return the OID for the given x.y.z.... style numeric string */ -int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, - const char *oid_str, size_t size) -{ - int ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - const char *str_ptr = oid_str; - const char *str_bound = oid_str + size; - unsigned int val = 0; - unsigned int component1, component2; - size_t encoded_len; - unsigned char *resized_mem; - - /* Count the number of dots to get a worst-case allocation size. */ - size_t num_dots = 0; - for (size_t i = 0; i < size; i++) { - if (oid_str[i] == '.') { - num_dots++; - } - } - /* Allocate maximum possible required memory: - * There are (num_dots + 1) integer components, but the first 2 share the - * same subidentifier, so we only need num_dots subidentifiers maximum. */ - if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) { - return MBEDTLS_ERR_ASN1_INVALID_DATA; - } - /* Each byte can store 7 bits, calculate number of bytes for a - * subidentifier: - * - * bytes = ceil(subidentifer_size * 8 / 7) - */ - size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7) - + 1; - size_t max_possible_bytes = num_dots * bytes_per_subidentifier; - oid->p = mbedtls_calloc(max_possible_bytes, 1); - if (oid->p == NULL) { - return MBEDTLS_ERR_ASN1_ALLOC_FAILED; - } - unsigned char *out_ptr = oid->p; - unsigned char *out_bound = oid->p + max_possible_bytes; - - ret = oid_parse_number(&component1, &str_ptr, str_bound); - if (ret != 0) { - goto error; - } - if (component1 > 2) { - /* First component can't be > 2 */ - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - if (str_ptr >= str_bound || *str_ptr != '.') { - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - str_ptr++; - - ret = oid_parse_number(&component2, &str_ptr, str_bound); - if (ret != 0) { - goto error; - } - if ((component1 < 2) && (component2 > 39)) { - /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */ - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - if (str_ptr < str_bound) { - if (*str_ptr == '.') { - str_ptr++; - } else { - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - } - - if (component2 > (UINT_MAX - (component1 * 40))) { - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - ret = oid_subidentifier_encode_into(&out_ptr, out_bound, - (component1 * 40) + component2); - if (ret != 0) { - goto error; - } - - while (str_ptr < str_bound) { - ret = oid_parse_number(&val, &str_ptr, str_bound); - if (ret != 0) { - goto error; - } - if (str_ptr < str_bound) { - if (*str_ptr == '.') { - str_ptr++; - } else { - ret = MBEDTLS_ERR_ASN1_INVALID_DATA; - goto error; - } - } - - ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val); - if (ret != 0) { - goto error; - } - } - - encoded_len = out_ptr - oid->p; - resized_mem = mbedtls_calloc(encoded_len, 1); - if (resized_mem == NULL) { - ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED; - goto error; - } - memcpy(resized_mem, oid->p, encoded_len); - mbedtls_free(oid->p); - oid->p = resized_mem; - oid->len = encoded_len; - - oid->tag = MBEDTLS_ASN1_OID; - - return 0; - -error: - mbedtls_free(oid->p); - oid->p = NULL; - oid->len = 0; - return ret; -} - -#endif /* MBEDTLS_OID_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk.c b/matter/mbedtls/tinycrypt/src/pk.c deleted file mode 100644 index 96b8ef9220..0000000000 --- a/matter/mbedtls/tinycrypt/src/pk.c +++ /dev/null @@ -1,982 +0,0 @@ -/* - * Public Key abstraction layer - * - * 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. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#include "pk_wrap.h" -#include "pkwrite.h" -#include "pk_internal.h" - -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) -#include "psa_util_internal.h" -#include "md_psa.h" -#endif - -#include -#include - -/* - * Initialise a mbedtls_pk_context - */ -void mbedtls_pk_init(mbedtls_pk_context *ctx) -{ - ctx->pk_info = NULL; - ctx->pk_ctx = NULL; -#if defined(MBEDTLS_PSA_CRYPTO_C) - ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT; -#endif /* MBEDTLS_PSA_CRYPTO_C */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw)); - ctx->pub_raw_len = 0; - ctx->ec_family = 0; - ctx->ec_bits = 0; -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -} - -/* - * Free (the components of) a mbedtls_pk_context - */ -void mbedtls_pk_free(mbedtls_pk_context *ctx) -{ - if (ctx == NULL) { - return; - } - - if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) { - ctx->pk_info->ctx_free_func(ctx->pk_ctx); - } - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - /* The ownership of the priv_id key for opaque keys is external of the PK - * module. It's the user responsibility to clear it after use. */ - if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) { - psa_destroy_key(ctx->priv_id); - } -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Initialize a restart context - */ -void mbedtls_pk_restart_init(mbedtls_pk_restart_ctx *ctx) -{ - ctx->pk_info = NULL; - ctx->rs_ctx = NULL; -} - -/* - * Free the components of a restart context - */ -void mbedtls_pk_restart_free(mbedtls_pk_restart_ctx *ctx) -{ - if (ctx == NULL || ctx->pk_info == NULL || - ctx->pk_info->rs_free_func == NULL) { - return; - } - - ctx->pk_info->rs_free_func(ctx->rs_ctx); - - ctx->pk_info = NULL; - ctx->rs_ctx = NULL; -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/* - * Get pk_info structure from type - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) -{ - switch (pk_type) { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_PK_RSA: - return &mbedtls_rsa_info; -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - case MBEDTLS_PK_ECKEY: - return &mbedtls_eckey_info; - case MBEDTLS_PK_ECKEY_DH: - return &mbedtls_eckeydh_info; -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) - case MBEDTLS_PK_ECDSA: - return &mbedtls_ecdsa_info; -#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ - /* MBEDTLS_PK_RSA_ALT omitted on purpose */ - default: - return NULL; - } -} - -/* - * Initialise context - */ -int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) -{ - if (info == NULL || ctx->pk_info != NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if ((info->ctx_alloc_func != NULL) && - ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - ctx->pk_info = info; - - return 0; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Initialise a PSA-wrapping context - */ -int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx, - const mbedtls_svc_key_id_t key) -{ - const mbedtls_pk_info_t *info = NULL; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t type; - - if (ctx == NULL || ctx->pk_info != NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (PSA_SUCCESS != psa_get_key_attributes(key, &attributes)) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - type = psa_get_key_type(&attributes); - psa_reset_key_attributes(&attributes); - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) { - info = &mbedtls_ecdsa_opaque_info; - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) { - info = &mbedtls_rsa_opaque_info; - } else { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - - ctx->pk_info = info; - ctx->priv_id = key; - - return 0; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Initialize an RSA-alt context - */ -int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func) -{ - mbedtls_rsa_alt_context *rsa_alt; - const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - - if (ctx->pk_info != NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - ctx->pk_info = info; - - rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; - - rsa_alt->key = key; - rsa_alt->decrypt_func = decrypt_func; - rsa_alt->sign_func = sign_func; - rsa_alt->key_len_func = key_len_func; - - return 0; -} -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/* - * Tell if a PK can do the operations of the given type - */ -int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) -{ - /* A context with null pk_info is not set up yet and can't do anything. - * For backward compatibility, also accept NULL instead of a context - * pointer. */ - if (ctx == NULL || ctx->pk_info == NULL) { - return 0; - } - - return ctx->pk_info->can_do(type); -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Tell if a PK can do the operations of the given PSA algorithm - */ -int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg, - psa_key_usage_t usage) -{ - psa_key_usage_t key_usage; - - /* A context with null pk_info is not set up yet and can't do anything. - * For backward compatibility, also accept NULL instead of a context - * pointer. */ - if (ctx == NULL || ctx->pk_info == NULL) { - return 0; - } - - /* Filter out non allowed algorithms */ - if (PSA_ALG_IS_ECDSA(alg) == 0 && - PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) == 0 && - PSA_ALG_IS_RSA_PSS(alg) == 0 && - alg != PSA_ALG_RSA_PKCS1V15_CRYPT && - PSA_ALG_IS_ECDH(alg) == 0) { - return 0; - } - - /* Filter out non allowed usage flags */ - if (usage == 0 || - (usage & ~(PSA_KEY_USAGE_SIGN_HASH | - PSA_KEY_USAGE_DECRYPT | - PSA_KEY_USAGE_DERIVE)) != 0) { - return 0; - } - - /* Wildcard hash is not allowed */ - if (PSA_ALG_IS_SIGN_HASH(alg) && - PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH) { - return 0; - } - - if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_OPAQUE) { - mbedtls_pk_type_t type; - - if (PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_ECDH(alg)) { - type = MBEDTLS_PK_ECKEY; - } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || - alg == PSA_ALG_RSA_PKCS1V15_CRYPT) { - type = MBEDTLS_PK_RSA; - } else if (PSA_ALG_IS_RSA_PSS(alg)) { - type = MBEDTLS_PK_RSASSA_PSS; - } else { - return 0; - } - - if (ctx->pk_info->can_do(type) == 0) { - return 0; - } - - switch (type) { - case MBEDTLS_PK_ECKEY: - key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE; - break; - case MBEDTLS_PK_RSA: - case MBEDTLS_PK_RSASSA_PSS: - key_usage = PSA_KEY_USAGE_SIGN_HASH | - PSA_KEY_USAGE_SIGN_MESSAGE | - PSA_KEY_USAGE_DECRYPT; - break; - default: - /* Should never happen */ - return 0; - } - - return (key_usage & usage) == usage; - } - - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t key_alg, key_alg2; - psa_status_t status; - - status = psa_get_key_attributes(ctx->priv_id, &attributes); - if (status != PSA_SUCCESS) { - return 0; - } - - key_alg = psa_get_key_algorithm(&attributes); - key_alg2 = psa_get_key_enrollment_algorithm(&attributes); - key_usage = psa_get_key_usage_flags(&attributes); - psa_reset_key_attributes(&attributes); - - if ((key_usage & usage) != usage) { - return 0; - } - - /* - * Common case: the key alg or alg2 only allows alg. - * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH - * directly. - * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with - * a fixed hash on key_alg/key_alg2. - */ - if (alg == key_alg || alg == key_alg2) { - return 1; - } - - /* - * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash, - * and alg is the same hash-and-sign family with any hash, - * then alg is compliant with this key alg - */ - if (PSA_ALG_IS_SIGN_HASH(alg)) { - - if (PSA_ALG_IS_SIGN_HASH(key_alg) && - PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH && - (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) { - return 1; - } - - if (PSA_ALG_IS_SIGN_HASH(key_alg2) && - PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH && - (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) { - return 1; - } - } - - return 0; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -/* - * Helper for mbedtls_pk_sign and mbedtls_pk_verify - */ -static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) -{ - if (*hash_len != 0) { - return 0; - } - - *hash_len = mbedtls_md_get_size_from_type(md_alg); - - if (*hash_len == 0) { - return -1; - } - - return 0; -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Helper to set up a restart context if needed - */ -static int pk_restart_setup(mbedtls_pk_restart_ctx *ctx, - const mbedtls_pk_info_t *info) -{ - /* Don't do anything if already set up or invalid */ - if (ctx == NULL || ctx->pk_info != NULL) { - return 0; - } - - /* Should never happen when we're called */ - if (info->rs_alloc_func == NULL || info->rs_free_func == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if ((ctx->rs_ctx = info->rs_alloc_func()) == NULL) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - ctx->pk_info = info; - - return 0; -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -/* - * Verify a signature (restartable) - */ -int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - mbedtls_pk_restart_ctx *rs_ctx) -{ - if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info == NULL || - pk_hashlen_helper(md_alg, &hash_len) != 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* optimization: use non-restartable version if restart disabled */ - if (rs_ctx != NULL && - mbedtls_ecp_restart_is_enabled() && - ctx->pk_info->verify_rs_func != NULL) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { - return ret; - } - - ret = ctx->pk_info->verify_rs_func(ctx, - md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx); - - if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { - mbedtls_pk_restart_free(rs_ctx); - } - - return ret; - } -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - (void) rs_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - if (ctx->pk_info->verify_func == NULL) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len, - sig, sig_len); -} - -/* - * Verify a signature - */ -int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - return mbedtls_pk_verify_restartable(ctx, md_alg, hash, hash_len, - sig, sig_len, NULL); -} - -/* - * Verify a signature with options - */ -int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (!mbedtls_pk_can_do(ctx, type)) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - if (type != MBEDTLS_PK_RSASSA_PSS) { - /* General case: no options */ - if (options != NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len); - } - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_pk_rsassa_pss_options *pss_opts; - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } -#endif - - if (options == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (pss_opts->mgf1_hash_id == md_alg) { - unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; - unsigned char *p; - int key_len; - size_t signature_length; - psa_status_t status = PSA_ERROR_DATA_CORRUPT; - psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT; - - psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg); - p = buf + sizeof(buf); - key_len = mbedtls_pk_write_pubkey(&p, buf, ctx); - - if (key_len < 0) { - return key_len; - } - - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, psa_sig_alg); - - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - psa_destroy_key(key_id); - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH - * on a valid signature with trailing data in a buffer, but - * mbedtls_psa_rsa_verify_hash requires the sig_len to be exact, - * so for this reason the passed sig_len is overwritten. Smaller - * signature lengths should not be accepted for verification. */ - signature_length = sig_len > mbedtls_pk_get_len(ctx) ? - mbedtls_pk_get_len(ctx) : sig_len; - status = psa_verify_hash(key_id, psa_sig_alg, hash, - hash_len, sig, signature_length); - destruction_status = psa_destroy_key(key_id); - - if (status == PSA_SUCCESS && sig_len > mbedtls_pk_get_len(ctx)) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - if (status == PSA_SUCCESS) { - status = destruction_status; - } - - return PSA_PK_RSA_TO_MBEDTLS_ERR(status); - } else -#endif - { - if (sig_len < mbedtls_pk_get_len(ctx)) { - return MBEDTLS_ERR_RSA_VERIFY_FAILED; - } - - ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), - md_alg, (unsigned int) hash_len, hash, - pss_opts->mgf1_hash_id, - pss_opts->expected_salt_len, - sig); - if (ret != 0) { - return ret; - } - - if (sig_len > mbedtls_pk_get_len(ctx)) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - return 0; - } -#else - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ -} - -/* - * Make a signature (restartable) - */ -int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_pk_restart_ctx *rs_ctx) -{ - if ((md_alg != MBEDTLS_MD_NONE || hash_len != 0) && hash == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info == NULL || pk_hashlen_helper(md_alg, &hash_len) != 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* optimization: use non-restartable version if restart disabled */ - if (rs_ctx != NULL && - mbedtls_ecp_restart_is_enabled() && - ctx->pk_info->sign_rs_func != NULL) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = pk_restart_setup(rs_ctx, ctx->pk_info)) != 0) { - return ret; - } - - ret = ctx->pk_info->sign_rs_func(ctx, md_alg, - hash, hash_len, - sig, sig_size, sig_len, - f_rng, p_rng, rs_ctx->rs_ctx); - - if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { - mbedtls_pk_restart_free(rs_ctx); - } - - return ret; - } -#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - (void) rs_ctx; -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - if (ctx->pk_info->sign_func == NULL) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - return ctx->pk_info->sign_func(ctx, md_alg, - hash, hash_len, - sig, sig_size, sig_len, - f_rng, p_rng); -} - -/* - * Make a signature - */ -int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - return mbedtls_pk_sign_restartable(ctx, md_alg, hash, hash_len, - sig, sig_size, sig_len, - f_rng, p_rng, NULL); -} - -#if defined(MBEDTLS_PSA_CRYPTO_C) -/* - * Make a signature given a signature type. - */ -int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type, - mbedtls_pk_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ -#if defined(MBEDTLS_RSA_C) - psa_algorithm_t psa_md_alg; -#endif /* MBEDTLS_RSA_C */ - *sig_len = 0; - - if (ctx->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (!mbedtls_pk_can_do(ctx, pk_type)) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - if (pk_type != MBEDTLS_PK_RSASSA_PSS) { - return mbedtls_pk_sign(ctx, md_alg, hash, hash_len, - sig, sig_size, sig_len, f_rng, p_rng); - } - -#if defined(MBEDTLS_RSA_C) - psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); - if (psa_md_alg == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) { - psa_status_t status; - - status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg), - hash, hash_len, - sig, sig_size, sig_len); - return PSA_PK_RSA_TO_MBEDTLS_ERR(status); - } - - return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg), - ctx->pk_ctx, hash, hash_len, - sig, sig_size, sig_len); -#else /* MBEDTLS_RSA_C */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -#endif /* !MBEDTLS_RSA_C */ - -} -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -/* - * Decrypt message - */ -int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - if (ctx->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info->decrypt_func == NULL) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - return ctx->pk_info->decrypt_func(ctx, input, ilen, - output, olen, osize, f_rng, p_rng); -} - -/* - * Encrypt message - */ -int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - if (ctx->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info->encrypt_func == NULL) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - return ctx->pk_info->encrypt_func(ctx, input, ilen, - output, olen, osize, f_rng, p_rng); -} - -/* - * Check public-private key pair - */ -int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, - const mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - if (pub->pk_info == NULL || - prv->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (f_rng == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (prv->pk_info->check_pair_func == NULL) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - - if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { - if (pub->pk_info->type != MBEDTLS_PK_RSA) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - } else { - if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) && - (pub->pk_info != prv->pk_info)) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - } - - return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub, - (mbedtls_pk_context *) prv, - f_rng, p_rng); -} - -/* - * Get key size in bits - */ -size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) -{ - /* For backward compatibility, accept NULL or a context that - * isn't set up yet, and return a fake value that should be safe. */ - if (ctx == NULL || ctx->pk_info == NULL) { - return 0; - } - - return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx); -} - -/* - * Export debug information - */ -int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) -{ - if (ctx->pk_info == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (ctx->pk_info->debug_func == NULL) { - return MBEDTLS_ERR_PK_TYPE_MISMATCH; - } - - ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items); - return 0; -} - -/* - * Access the PK type name - */ -const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) -{ - if (ctx == NULL || ctx->pk_info == NULL) { - return "invalid PK"; - } - - return ctx->pk_info->name; -} - -/* - * Access the PK type - */ -mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) -{ - if (ctx == NULL || ctx->pk_info == NULL) { - return MBEDTLS_PK_NONE; - } - - return ctx->pk_info->type; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Load the key to a PSA key slot, - * then turn the PK context into a wrapper for that key slot. - * - * Currently only works for EC & RSA private keys. - */ -int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk, - mbedtls_svc_key_id_t *key, - psa_algorithm_t alg, - psa_key_usage_t usage, - psa_algorithm_t alg2) -{ -#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C) - ((void) pk); - ((void) key); - ((void) alg); - ((void) usage); - ((void) alg2); -#else /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) { - size_t d_len; - psa_ecc_family_t curve_id; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t key_type; - size_t bits; - psa_status_t status; - - /* export the private key material in the format PSA wants */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - unsigned char d[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - status = psa_export_key(pk->priv_id, d, sizeof(d), &d_len); - if (status != PSA_SUCCESS) { - return psa_pk_status_to_mbedtls(status); - } - - curve_id = pk->ec_family; - bits = pk->ec_bits; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - unsigned char d[MBEDTLS_ECP_MAX_BYTES]; - mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - d_len = PSA_BITS_TO_BYTES(ec->grp.nbits); - if ((ret = mbedtls_ecp_write_key(ec, d, d_len)) != 0) { - return ret; - } - - curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id); - - /* prepare the key attributes */ - psa_set_key_type(&attributes, key_type); - psa_set_key_bits(&attributes, bits); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, d, d_len, key); - mbedtls_platform_zeroize(d, sizeof(d)); - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) { - unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - int key_len; - psa_status_t status; - - /* export the private key material in the format PSA wants */ - key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* prepare the key attributes */ - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk)); - psa_set_key_usage_flags(&attributes, usage); - psa_set_key_algorithm(&attributes, alg); - if (alg2 != PSA_ALG_NONE) { - psa_set_key_enrollment_algorithm(&attributes, alg2); - } - - /* import private key into PSA */ - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, - key_len, key); - - mbedtls_platform_zeroize(buf, sizeof(buf)); - - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - /* make PK context wrap the key slot */ - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - return mbedtls_pk_setup_opaque(pk, *key); - } else -#endif /* MBEDTLS_RSA_C */ -#endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */ - return MBEDTLS_ERR_PK_TYPE_MISMATCH; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk_wrap.c b/matter/mbedtls/tinycrypt/src/pk_wrap.c deleted file mode 100644 index 5b78dfb426..0000000000 --- a/matter/mbedtls/tinycrypt/src/pk_wrap.c +++ /dev/null @@ -1,1850 +0,0 @@ -/* - * Public Key abstraction layer: wrapper functions - * - * 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. - */ - -#include "common.h" - -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_PK_C) -#include "pk_wrap.h" -#include "pk_internal.h" -#include "mbedtls/error.h" -#include "md_psa.h" - -/* Even if RSA not activated, for the sake of RSA-alt */ -#include "mbedtls/rsa.h" - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C) -#include "pkwrite.h" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) -#include "psa_util_internal.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" - -#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) -#include "mbedtls/asn1write.h" -#include "mbedtls/asn1.h" -#endif -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#include "mbedtls/platform.h" - -#include -#include -#include - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_PSA_CRYPTO_C) -int mbedtls_pk_error_from_psa(psa_status_t status) -{ - switch (status) { - case PSA_SUCCESS: - return 0; - case PSA_ERROR_INVALID_HANDLE: - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - case PSA_ERROR_NOT_PERMITTED: - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; - case PSA_ERROR_BUFFER_TOO_SMALL: - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; - case PSA_ERROR_NOT_SUPPORTED: - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - case PSA_ERROR_INVALID_ARGUMENT: - return MBEDTLS_ERR_PK_INVALID_ALG; - case PSA_ERROR_INSUFFICIENT_MEMORY: - return MBEDTLS_ERR_PK_ALLOC_FAILED; - case PSA_ERROR_BAD_STATE: - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - case PSA_ERROR_COMMUNICATION_FAILURE: - case PSA_ERROR_HARDWARE_FAILURE: - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - case PSA_ERROR_DATA_CORRUPT: - case PSA_ERROR_DATA_INVALID: - case PSA_ERROR_STORAGE_FAILURE: - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - case PSA_ERROR_CORRUPTION_DETECTED: - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - default: - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; - } -} - -#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ - defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) -int mbedtls_pk_error_from_psa_rsa(psa_status_t status) -{ - switch (status) { - case PSA_ERROR_NOT_PERMITTED: - case PSA_ERROR_INVALID_ARGUMENT: - case PSA_ERROR_INVALID_HANDLE: - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - case PSA_ERROR_BUFFER_TOO_SMALL: - return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - case PSA_ERROR_INSUFFICIENT_ENTROPY: - return MBEDTLS_ERR_RSA_RNG_FAILED; - case PSA_ERROR_INVALID_SIGNATURE: - return MBEDTLS_ERR_RSA_VERIFY_FAILED; - case PSA_ERROR_INVALID_PADDING: - return MBEDTLS_ERR_RSA_INVALID_PADDING; - case PSA_SUCCESS: - return 0; - case PSA_ERROR_NOT_SUPPORTED: - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - case PSA_ERROR_INSUFFICIENT_MEMORY: - return MBEDTLS_ERR_PK_ALLOC_FAILED; - case PSA_ERROR_BAD_STATE: - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - case PSA_ERROR_COMMUNICATION_FAILURE: - case PSA_ERROR_HARDWARE_FAILURE: - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - case PSA_ERROR_DATA_CORRUPT: - case PSA_ERROR_DATA_INVALID: - case PSA_ERROR_STORAGE_FAILURE: - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - case PSA_ERROR_CORRUPTION_DETECTED: - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - default: - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; - } -} -#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) -int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status) -{ - switch (status) { - case PSA_ERROR_NOT_PERMITTED: - case PSA_ERROR_INVALID_ARGUMENT: - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - case PSA_ERROR_INVALID_HANDLE: - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - case PSA_ERROR_BUFFER_TOO_SMALL: - return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - case PSA_ERROR_INSUFFICIENT_ENTROPY: - return MBEDTLS_ERR_ECP_RANDOM_FAILED; - case PSA_ERROR_INVALID_SIGNATURE: - return MBEDTLS_ERR_ECP_VERIFY_FAILED; - case PSA_SUCCESS: - return 0; - case PSA_ERROR_NOT_SUPPORTED: - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - case PSA_ERROR_INSUFFICIENT_MEMORY: - return MBEDTLS_ERR_PK_ALLOC_FAILED; - case PSA_ERROR_BAD_STATE: - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - case PSA_ERROR_COMMUNICATION_FAILURE: - case PSA_ERROR_HARDWARE_FAILURE: - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - case PSA_ERROR_DATA_CORRUPT: - case PSA_ERROR_DATA_INVALID: - case PSA_ERROR_STORAGE_FAILURE: - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - case PSA_ERROR_CORRUPTION_DETECTED: - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - default: - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; - } -} -#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_RSA_C) -static int rsa_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_RSA || - type == MBEDTLS_PK_RSASSA_PSS; -} - -static size_t rsa_get_bitlen(mbedtls_pk_context *pk) -{ - const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx; - return 8 * mbedtls_rsa_get_len(rsa); -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; - psa_algorithm_t psa_alg_md = - PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); - size_t rsa_len = mbedtls_rsa_get_len(rsa); - - if (md_alg == MBEDTLS_MD_NONE -#if SIZE_MAX > UINT_MAX - && UINT_MAX < hash_len -#endif - ) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (sig_len < rsa_len) { - return MBEDTLS_ERR_RSA_VERIFY_FAILED; - } - - /* mbedtls_pk_write_pubkey_der() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &mbedtls_rsa_info; - key.pk_ctx = rsa; - key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, psa_alg_md); - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); - - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len, - sig, sig_len); - if (status != PSA_SUCCESS) { - ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); - goto cleanup; - } - ret = 0; - -cleanup: - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - - return ret; -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - size_t rsa_len = mbedtls_rsa_get_len(rsa); - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } -#endif - - if (sig_len < rsa_len) { - return MBEDTLS_ERR_RSA_VERIFY_FAILED; - } - - if ((ret = mbedtls_rsa_pkcs1_verify(rsa, md_alg, - (unsigned int) hash_len, - hash, sig)) != 0) { - return ret; - } - - /* The buffer contains a valid signature followed by extra data. - * We have a special error code for that so that so that callers can - * use mbedtls_pk_verify() to check "Does the buffer start with a - * valid signature?" and not just "Does the buffer contain a valid - * signature?". */ - if (sig_len > rsa_len) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - return 0; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PSA_CRYPTO_C) -int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg, - mbedtls_rsa_context *rsa_ctx, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, - size_t *sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - unsigned char *buf = NULL; - buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); - if (buf == NULL) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - mbedtls_pk_info_t pk_info = mbedtls_rsa_info; - - *sig_len = mbedtls_rsa_get_len(rsa_ctx); - if (sig_size < *sig_len) { - mbedtls_free(buf); - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; - } - - /* mbedtls_pk_write_key_der() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &pk_info; - key.pk_ctx = rsa_ctx; - key_len = mbedtls_pk_write_key_der(&key, buf, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES); - if (key_len <= 0) { - mbedtls_free(buf); - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, alg); - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - - status = psa_import_key(&attributes, - buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - status = psa_sign_hash(key_id, alg, hash, hash_len, - sig, sig_size, sig_len); - if (status != PSA_SUCCESS) { - ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - ret = 0; - -cleanup: - mbedtls_free(buf); - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - return ret; -} -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - ((void) f_rng); - ((void) p_rng); - - psa_algorithm_t psa_md_alg; - psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg); - if (psa_md_alg == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN( - psa_md_alg), - pk->pk_ctx, hash, hash_len, - sig, sig_size, sig_len); -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - -#if SIZE_MAX > UINT_MAX - if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } -#endif - - *sig_len = mbedtls_rsa_get_len(rsa); - if (sig_size < *sig_len) { - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; - } - - return mbedtls_rsa_pkcs1_sign(rsa, f_rng, p_rng, - md_alg, (unsigned int) hash_len, - hash, sig); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static int rsa_decrypt_wrap(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES]; - - ((void) f_rng); - ((void) p_rng); - -#if !defined(MBEDTLS_RSA_ALT) - if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { - return MBEDTLS_ERR_RSA_INVALID_PADDING; - } -#endif /* !MBEDTLS_RSA_ALT */ - - if (ilen != mbedtls_rsa_get_len(rsa)) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - /* mbedtls_pk_write_key_der() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &mbedtls_rsa_info; - key.pk_ctx = rsa; - key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); - - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, - input, ilen, - NULL, 0, - output, osize, olen); - if (status != PSA_SUCCESS) { - ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - ret = 0; - -cleanup: - mbedtls_platform_zeroize(buf, sizeof(buf)); - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - - return ret; -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_decrypt_wrap(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - - if (ilen != mbedtls_rsa_get_len(rsa)) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng, - olen, input, output, osize); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static int rsa_encrypt_wrap(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_status_t status; - mbedtls_pk_context key; - int key_len; - unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES]; - - ((void) f_rng); - ((void) p_rng); - -#if !defined(MBEDTLS_RSA_ALT) - if (rsa->padding != MBEDTLS_RSA_PKCS_V15) { - return MBEDTLS_ERR_RSA_INVALID_PADDING; - } -#endif - - if (mbedtls_rsa_get_len(rsa) > osize) { - return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - } - - /* mbedtls_pk_write_pubkey_der() expects a full PK context; - * re-construct one to make it happy */ - key.pk_info = &mbedtls_rsa_info; - key.pk_ctx = rsa; - key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf)); - if (key_len <= 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); - psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT); - psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY); - - status = psa_import_key(&attributes, - buf + sizeof(buf) - key_len, key_len, - &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT, - input, ilen, - NULL, 0, - output, osize, olen); - if (status != PSA_SUCCESS) { - ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - ret = 0; - -cleanup: - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - - return ret; -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int rsa_encrypt_wrap(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - *olen = mbedtls_rsa_get_len(rsa); - - if (*olen > osize) { - return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - } - - return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng, - ilen, input, output); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - (void) f_rng; - (void) p_rng; - return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx, - (const mbedtls_rsa_context *) prv->pk_ctx); -} - -static void *rsa_alloc_wrap(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_context)); - - if (ctx != NULL) { - mbedtls_rsa_init((mbedtls_rsa_context *) ctx); - } - - return ctx; -} - -static void rsa_free_wrap(void *ctx) -{ - mbedtls_rsa_free((mbedtls_rsa_context *) ctx); - mbedtls_free(ctx); -} - -static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) -{ -#if defined(MBEDTLS_RSA_ALT) - /* Not supported */ - (void) pk; - (void) items; -#else - mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.N"; - items->value = &(rsa->N); - - items++; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.E"; - items->value = &(rsa->E); -#endif -} - -const mbedtls_pk_info_t mbedtls_rsa_info = { - .type = MBEDTLS_PK_RSA, - .name = "RSA", - .get_bitlen = rsa_get_bitlen, - .can_do = rsa_can_do, - .verify_func = rsa_verify_wrap, - .sign_func = rsa_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, - .rs_alloc_func = NULL, - .rs_free_func = NULL, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = rsa_decrypt_wrap, - .encrypt_func = rsa_encrypt_wrap, - .check_pair_func = rsa_check_pair_wrap, - .ctx_alloc_func = rsa_alloc_wrap, - .ctx_free_func = rsa_free_wrap, - .debug_func = rsa_debug, -}; -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -/* - * Generic EC key - */ -static int eckey_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH || - type == MBEDTLS_PK_ECDSA; -} - -static size_t eckey_get_bitlen(mbedtls_pk_context *pk) -{ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - return pk->ec_bits; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; - return ecp->grp.pbits; -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -} - -#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of - * those integers and convert it to the fixed-length encoding expected by PSA. - */ -static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end, - unsigned char *to, size_t to_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t unpadded_len, padding_len; - - if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len, - MBEDTLS_ASN1_INTEGER)) != 0) { - return ret; - } - - while (unpadded_len > 0 && **from == 0x00) { - (*from)++; - unpadded_len--; - } - - if (unpadded_len > to_len || unpadded_len == 0) { - return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - } - - padding_len = to_len - unpadded_len; - memset(to, 0x00, padding_len); - memcpy(to + padding_len, *from, unpadded_len); - (*from) += unpadded_len; - - return 0; -} - -/* - * Convert a signature from an ASN.1 sequence of two integers - * to a raw {r,s} buffer. Note: the provided sig buffer must be at least - * twice as big as int_size. - */ -static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end, - unsigned char *sig, size_t int_size) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t tmp_size; - - if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return ret; - } - - /* Extract r */ - if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) { - return ret; - } - /* Extract s */ - if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) { - return ret; - } - - return 0; -} - -/* Common helper for ECDSA verify using PSA functions. */ -static int ecdsa_verify_psa(unsigned char *key, size_t key_len, - psa_ecc_family_t curve, size_t curve_bits, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; - size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits); - unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE]; - unsigned char *p; - psa_status_t status; - - if (curve == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&attributes, psa_sig_md); - - status = psa_import_key(&attributes, key, key_len, &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - if (signature_len > sizeof(extracted_sig)) { - ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; - goto cleanup; - } - - p = (unsigned char *) sig; - /* extract_ecdsa_sig's last parameter is the size - * of each integer to be parsed, so it's actually half - * the size of the signature. */ - if ((ret = extract_ecdsa_sig(&p, sig + sig_len, extracted_sig, - signature_len/2)) != 0) { - goto cleanup; - } - - status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len, - extracted_sig, signature_len); - if (status != PSA_SUCCESS) { - ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - if (p != sig + sig_len) { - ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - goto cleanup; - } - ret = 0; - -cleanup: - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - - return ret; -} - -static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - (void) md_alg; - unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; - size_t key_len; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - psa_ecc_family_t curve; - size_t curve_bits; - psa_status_t status; - - status = psa_get_key_attributes(pk->priv_id, &key_attr); - if (status != PSA_SUCCESS) { - return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - } - curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr)); - curve_bits = psa_get_key_bits(&key_attr); - psa_reset_key_attributes(&key_attr); - - status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len); - if (status != PSA_SUCCESS) { - return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - } - - return ecdsa_verify_psa(key, key_len, curve, curve_bits, - hash, hash_len, sig, sig_len); -} - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -static int ecdsa_verify_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - (void) md_alg; - psa_ecc_family_t curve = pk->ec_family; - size_t curve_bits = pk->ec_bits; - - return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits, - hash, hash_len, sig, sig_len); -} -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int ecdsa_verify_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - (void) md_alg; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_keypair *ctx = pk->pk_ctx; - unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t key_len; - size_t curve_bits; - psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); - - ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &key_len, key, sizeof(key)); - if (ret != 0) { - return ret; - } - - return ecdsa_verify_psa(key, key_len, curve, curve_bits, - hash, hash_len, sig, sig_len); -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx, - hash, hash_len, sig, sig_len); - - if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - return ret; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ - -#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* - * Simultaneously convert and move raw MPI from the beginning of a buffer - * to an ASN.1 MPI at the end of the buffer. - * See also mbedtls_asn1_write_mpi(). - * - * p: pointer to the end of the output buffer - * start: start of the output buffer, and also of the mpi to write at the end - * n_len: length of the mpi to read from start - */ -static int asn1_write_mpibuf(unsigned char **p, unsigned char *start, - size_t n_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - - if ((size_t) (*p - start) < n_len) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - len = n_len; - *p -= len; - memmove(*p, start, len); - - /* ASN.1 DER encoding requires minimal length, so skip leading 0s. - * Neither r nor s should be 0, but as a failsafe measure, still detect - * that rather than overflowing the buffer in case of a PSA error. */ - while (len > 0 && **p == 0x00) { - ++(*p); - --len; - } - - /* this is only reached if the signature was invalid */ - if (len == 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - - /* if the msb is 1, ASN.1 requires that we prepend a 0. - * Neither r nor s can be 0, so we can assume len > 0 at all times. */ - if (**p & 0x80) { - if (*p - start < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, - MBEDTLS_ASN1_INTEGER)); - - return (int) len; -} - -/* Transcode signature from PSA format to ASN.1 sequence. - * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of - * MPIs, and in-place. - * - * [in/out] sig: the signature pre- and post-transcoding - * [in/out] sig_len: signature length pre- and post-transcoding - * [int] buf_len: the available size the in/out buffer - */ -static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len, - size_t buf_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - const size_t rs_len = *sig_len / 2; - unsigned char *p = sig + buf_len; - - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len)); - MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - memmove(sig, p, len); - *sig_len = len; - - return 0; -} - -/* Common helper for ECDSA sign using PSA functions. */ -static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_status_t status; - psa_algorithm_t psa_sig_md; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t alg; - - status = psa_get_key_attributes(key_id, &key_attr); - if (status != PSA_SUCCESS) { - return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - } - alg = psa_get_key_algorithm(&key_attr); - psa_reset_key_attributes(&key_attr); - - if (PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)) { - psa_sig_md = PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); - } else { - psa_sig_md = PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); - } - - status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len, - sig, sig_size, sig_len); - if (status != PSA_SUCCESS) { - return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - } - - ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size); - - return ret; -} - -static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, - size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - ((void) f_rng); - ((void) p_rng); - - return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size, - sig_len); -} - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up - * using the same function. */ -#define ecdsa_sign_wrap ecdsa_opaque_sign_wrap -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_status_t status; - mbedtls_ecp_keypair *ctx = pk->pk_ctx; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - size_t curve_bits; - psa_ecc_family_t curve = - mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits); - size_t key_len = PSA_BITS_TO_BYTES(curve_bits); -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - psa_algorithm_t psa_sig_md = - PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); -#else - psa_algorithm_t psa_sig_md = - PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)); -#endif - ((void) f_rng); - ((void) p_rng); - - if (curve == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - if (key_len > sizeof(buf)) { - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - } - ret = mbedtls_mpi_write_binary(&ctx->d, buf, key_len); - if (ret != 0) { - goto cleanup; - } - - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); - psa_set_key_algorithm(&attributes, psa_sig_md); - - status = psa_import_key(&attributes, buf, key_len, &key_id); - if (status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - goto cleanup; - } - - ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len); - -cleanup: - mbedtls_platform_zeroize(buf, sizeof(buf)); - status = psa_destroy_key(key_id); - if (ret == 0 && status != PSA_SUCCESS) { - ret = PSA_PK_TO_MBEDTLS_ERR(status); - } - - return ret; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx, - md_alg, hash, hash_len, - sig, sig_size, sig_len, - f_rng, p_rng); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* Forward declarations */ -static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx); - -static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx); - -/* - * Restart context for ECDSA operations with ECKEY context - * - * We need to store an actual ECDSA context, as we need to pass the same to - * the underlying ecdsa function, so we can't create it on the fly every time. - */ -typedef struct { - mbedtls_ecdsa_restart_ctx ecdsa_rs; - mbedtls_ecdsa_context ecdsa_ctx; -} eckey_restart_ctx; - -static void *eckey_rs_alloc(void) -{ - eckey_restart_ctx *rs_ctx; - - void *ctx = mbedtls_calloc(1, sizeof(eckey_restart_ctx)); - - if (ctx != NULL) { - rs_ctx = ctx; - mbedtls_ecdsa_restart_init(&rs_ctx->ecdsa_rs); - mbedtls_ecdsa_init(&rs_ctx->ecdsa_ctx); - } - - return ctx; -} - -static void eckey_rs_free(void *ctx) -{ - eckey_restart_ctx *rs_ctx; - - if (ctx == NULL) { - return; - } - - rs_ctx = ctx; - mbedtls_ecdsa_restart_free(&rs_ctx->ecdsa_rs); - mbedtls_ecdsa_free(&rs_ctx->ecdsa_ctx); - - mbedtls_free(ctx); -} - -static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if (rs == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* set up our own sub-context if needed (that is, on first run) */ - if (rs->ecdsa_ctx.grp.pbits == 0) { - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); - } - - MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk, - md_alg, hash, hash_len, - sig, sig_len, &rs->ecdsa_rs)); - -cleanup: - return ret; -} - -static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - eckey_restart_ctx *rs = rs_ctx; - - /* Should never happen */ - if (rs == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* set up our own sub-context if needed (that is, on first run) */ - if (rs->ecdsa_ctx.grp.pbits == 0) { - MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx)); - } - - MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg, - hash, hash_len, sig, sig_size, sig_len, - f_rng, p_rng, &rs->ecdsa_rs)); - -cleanup: - return ret; -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t prv_key_len; - mbedtls_svc_key_id_t key_id = prv->priv_id; - - status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), - &prv_key_len); - ret = PSA_PK_TO_MBEDTLS_ERR(status); - if (ret != 0) { - return ret; - } - - if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return 0; -} -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv) -{ - psa_status_t status; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t prv_key_len; - psa_status_t destruction_status; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t pub_key_len; - size_t curve_bits; - const psa_ecc_family_t curve = - mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits); - const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits); - - if (curve == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); - - ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d, - prv_key_buf, curve_bytes); - if (ret != 0) { - mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); - return ret; - } - - status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id); - mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf)); - ret = PSA_PK_TO_MBEDTLS_ERR(status); - if (ret != 0) { - return ret; - } - - // From now on prv_key_buf is used to store the public key of prv. - status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf), - &prv_key_len); - ret = PSA_PK_TO_MBEDTLS_ERR(status); - destruction_status = psa_destroy_key(key_id); - if (ret != 0) { - return ret; - } else if (destruction_status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(destruction_status); - } - - ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp, - &mbedtls_pk_ec_rw(*pub)->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &pub_key_len, pub_key_buf, - sizeof(pub_key_buf)); - if (ret != 0) { - return ret; - } - - if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return 0; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - -static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - (void) f_rng; - (void) p_rng; - return eckey_check_pair_psa(pub, prv); -} -#else /* MBEDTLS_USE_PSA_CRYPTO */ -static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx, - (const mbedtls_ecp_keypair *) prv->pk_ctx, - f_rng, p_rng); -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up - * using the same function. */ -#define ecdsa_opaque_check_pair_wrap eckey_check_pair_wrap -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub, - mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - psa_status_t status; - uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; - size_t exp_pub_key_len = 0; - uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; - size_t pub_key_len = 0; - int ret; - (void) f_rng; - (void) p_rng; - - status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key), - &exp_pub_key_len); - if (status != PSA_SUCCESS) { - ret = psa_pk_status_to_mbedtls(status); - return ret; - } - ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp), - &(mbedtls_pk_ec_ro(*pub)->Q), - MBEDTLS_ECP_PF_UNCOMPRESSED, - &pub_key_len, pub_key, sizeof(pub_key)); - if (ret != 0) { - return ret; - } - if ((exp_pub_key_len != pub_key_len) || - memcmp(exp_pub_key, pub_key, exp_pub_key_len)) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - return 0; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) -static void *eckey_alloc_wrap(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair)); - - if (ctx != NULL) { - mbedtls_ecp_keypair_init(ctx); - } - - return ctx; -} - -static void eckey_free_wrap(void *ctx) -{ - mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx); - mbedtls_free(ctx); -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - -static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items) -{ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - items->type = MBEDTLS_PK_DEBUG_PSA_EC; - items->name = "eckey.Q"; - items->value = pk; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx; - items->type = MBEDTLS_PK_DEBUG_ECP; - items->name = "eckey.Q"; - items->value = &(ecp->Q); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -} - -const mbedtls_pk_info_t mbedtls_eckey_info = { - .type = MBEDTLS_PK_ECKEY, - .name = "EC", - .get_bitlen = eckey_get_bitlen, - .can_do = eckey_can_do, -#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) - .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ -#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ - .verify_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ -#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) - .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ -#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ - .sign_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = eckey_verify_rs_wrap, - .sign_rs_func = eckey_sign_rs_wrap, - .rs_alloc_func = eckey_rs_alloc, - .rs_free_func = eckey_rs_free, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = NULL, - .encrypt_func = NULL, - .check_pair_func = eckey_check_pair_wrap, -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .ctx_alloc_func = eckey_alloc_wrap, - .ctx_free_func = eckey_free_wrap, -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .debug_func = eckey_debug, -}; - -/* - * EC key restricted to ECDH - */ -static int eckeydh_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH; -} - -const mbedtls_pk_info_t mbedtls_eckeydh_info = { - .type = MBEDTLS_PK_ECKEY_DH, - .name = "EC_DH", - .get_bitlen = eckey_get_bitlen, /* Same underlying key structure */ - .can_do = eckeydh_can_do, - .verify_func = NULL, - .sign_func = NULL, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = NULL, - .encrypt_func = NULL, - .check_pair_func = eckey_check_pair_wrap, -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .ctx_alloc_func = eckey_alloc_wrap, /* Same underlying key structure */ - .ctx_free_func = eckey_free_wrap, /* Same underlying key structure */ -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .debug_func = eckey_debug, /* Same underlying key structure */ -}; - -#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) -static int ecdsa_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_ECDSA; -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature_restartable( - (mbedtls_ecdsa_context *) pk->pk_ctx, - hash, hash_len, sig, sig_len, - (mbedtls_ecdsa_restart_ctx *) rs_ctx); - - if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) { - return MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; - } - - return ret; -} - -static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx) -{ - return mbedtls_ecdsa_write_signature_restartable( - (mbedtls_ecdsa_context *) pk->pk_ctx, - md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, - (mbedtls_ecdsa_restart_ctx *) rs_ctx); - -} - -static void *ecdsa_rs_alloc(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecdsa_restart_ctx)); - - if (ctx != NULL) { - mbedtls_ecdsa_restart_init(ctx); - } - - return ctx; -} - -static void ecdsa_rs_free(void *ctx) -{ - mbedtls_ecdsa_restart_free(ctx); - mbedtls_free(ctx); -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -const mbedtls_pk_info_t mbedtls_ecdsa_info = { - .type = MBEDTLS_PK_ECDSA, - .name = "ECDSA", - .get_bitlen = eckey_get_bitlen, /* Compatible key structures */ - .can_do = ecdsa_can_do, -#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) - .verify_func = ecdsa_verify_wrap, /* Compatible key structures */ -#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ - .verify_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ -#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) - .sign_func = ecdsa_sign_wrap, /* Compatible key structures */ -#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ - .sign_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = ecdsa_verify_rs_wrap, - .sign_rs_func = ecdsa_sign_rs_wrap, - .rs_alloc_func = ecdsa_rs_alloc, - .rs_free_func = ecdsa_rs_free, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = NULL, - .encrypt_func = NULL, - .check_pair_func = eckey_check_pair_wrap, /* Compatible key structures */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .ctx_alloc_func = eckey_alloc_wrap, /* Compatible key structures */ - .ctx_free_func = eckey_free_wrap, /* Compatible key structures */ -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - .debug_func = eckey_debug, /* Compatible key structures */ -}; -#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */ -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Support for alternative RSA-private implementations - */ - -static int rsa_alt_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_RSA; -} - -static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk) -{ - const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; - - return 8 * rsa_alt->key_len_func(rsa_alt->key); -} - -static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; - -#if SIZE_MAX > UINT_MAX - if (UINT_MAX < hash_len) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } -#endif - - *sig_len = rsa_alt->key_len_func(rsa_alt->key); - if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - if (*sig_len > sig_size) { - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; - } - - return rsa_alt->sign_func(rsa_alt->key, f_rng, p_rng, - md_alg, (unsigned int) hash_len, hash, sig); -} - -static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx; - - ((void) f_rng); - ((void) p_rng); - - if (ilen != rsa_alt->key_len_func(rsa_alt->key)) { - return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; - } - - return rsa_alt->decrypt_func(rsa_alt->key, - olen, input, output, osize); -} - -#if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char hash[32]; - size_t sig_len = 0; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (rsa_alt_get_bitlen(prv) != rsa_get_bitlen(pub)) { - return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - } - - memset(hash, 0x2a, sizeof(hash)); - - if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE, - hash, sizeof(hash), - sig, sizeof(sig), &sig_len, - f_rng, p_rng)) != 0) { - return ret; - } - - if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE, - hash, sizeof(hash), sig, sig_len) != 0) { - return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - } - - return 0; -} -#endif /* MBEDTLS_RSA_C */ - -static void *rsa_alt_alloc_wrap(void) -{ - void *ctx = mbedtls_calloc(1, sizeof(mbedtls_rsa_alt_context)); - - if (ctx != NULL) { - memset(ctx, 0, sizeof(mbedtls_rsa_alt_context)); - } - - return ctx; -} - -static void rsa_alt_free_wrap(void *ctx) -{ - mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context)); -} - -const mbedtls_pk_info_t mbedtls_rsa_alt_info = { - .type = MBEDTLS_PK_RSA_ALT, - .name = "RSA-alt", - .get_bitlen = rsa_alt_get_bitlen, - .can_do = rsa_alt_can_do, - .verify_func = NULL, - .sign_func = rsa_alt_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, - .rs_alloc_func = NULL, - .rs_free_func = NULL, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = rsa_alt_decrypt_wrap, - .encrypt_func = NULL, -#if defined(MBEDTLS_RSA_C) - .check_pair_func = rsa_alt_check_pair, -#else - .check_pair_func = NULL, -#endif - .ctx_alloc_func = rsa_alt_alloc_wrap, - .ctx_free_func = rsa_alt_free_wrap, - .debug_func = NULL, -}; -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static size_t opaque_get_bitlen(mbedtls_pk_context *pk) -{ - size_t bits; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - - if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) { - return 0; - } - - bits = psa_get_key_bits(&attributes); - psa_reset_key_attributes(&attributes); - return bits; -} - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -static int ecdsa_opaque_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECDSA; -} - -const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = { - .type = MBEDTLS_PK_OPAQUE, - .name = "Opaque", - .get_bitlen = opaque_get_bitlen, - .can_do = ecdsa_opaque_can_do, -#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) - .verify_func = ecdsa_opaque_verify_wrap, -#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ - .verify_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */ -#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) - .sign_func = ecdsa_opaque_sign_wrap, -#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */ - .sign_func = NULL, -#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, - .rs_alloc_func = NULL, - .rs_free_func = NULL, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - .decrypt_func = NULL, - .encrypt_func = NULL, - .check_pair_func = ecdsa_opaque_check_pair_wrap, - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, - .debug_func = NULL, -}; -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -static int rsa_opaque_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_RSA || - type == MBEDTLS_PK_RSASSA_PSS; -} - -#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) -static int rsa_opaque_decrypt(mbedtls_pk_context *pk, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - psa_status_t status; - - /* PSA has its own RNG */ - (void) f_rng; - (void) p_rng; - - status = psa_asymmetric_decrypt(pk->priv_id, PSA_ALG_RSA_PKCS1V15_CRYPT, - input, ilen, - NULL, 0, - output, osize, olen); - if (status != PSA_SUCCESS) { - return PSA_PK_RSA_TO_MBEDTLS_ERR(status); - } - - return 0; -} -#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ - -static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ -#if defined(MBEDTLS_RSA_C) - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_algorithm_t alg; - psa_key_type_t type; - psa_status_t status; - - /* PSA has its own RNG */ - (void) f_rng; - (void) p_rng; - - status = psa_get_key_attributes(pk->priv_id, &attributes); - if (status != PSA_SUCCESS) { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - - type = psa_get_key_type(&attributes); - psa_reset_key_attributes(&attributes); - - if (PSA_KEY_TYPE_IS_RSA(type)) { - alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg)); - } else { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - - /* make the signature */ - status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, - sig, sig_size, sig_len); - if (status != PSA_SUCCESS) { - if (PSA_KEY_TYPE_IS_RSA(type)) { - return PSA_PK_RSA_TO_MBEDTLS_ERR(status); - } else { - return PSA_PK_TO_MBEDTLS_ERR(status); - } - } - - return 0; -#else /* !MBEDTLS_RSA_C */ - ((void) pk); - ((void) md_alg); - ((void) hash); - ((void) hash_len); - ((void) sig); - ((void) sig_size); - ((void) sig_len); - ((void) f_rng); - ((void) p_rng); - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -#endif /* !MBEDTLS_RSA_C */ -} - -const mbedtls_pk_info_t mbedtls_rsa_opaque_info = { - .type = MBEDTLS_PK_OPAQUE, - .name = "Opaque", - .get_bitlen = opaque_get_bitlen, - .can_do = rsa_opaque_can_do, - .verify_func = NULL, - .sign_func = rsa_opaque_sign_wrap, -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, - .rs_alloc_func = NULL, - .rs_free_func = NULL, -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ -#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) - .decrypt_func = rsa_opaque_decrypt, -#else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ - .decrypt_func = NULL, -#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ - .encrypt_func = NULL, - .check_pair_func = NULL, - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, - .debug_func = NULL, -}; - -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#endif /* MBEDTLS_PK_C */ diff --git a/matter/mbedtls/tinycrypt/src/pk_wrap.h b/matter/mbedtls/tinycrypt/src/pk_wrap.h deleted file mode 100644 index b1e02180a5..0000000000 --- a/matter/mbedtls/tinycrypt/src/pk_wrap.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * \file pk_wrap.h - * - * \brief Public Key abstraction layer: wrapper functions - */ -/* - * 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. - */ - -#ifndef MBEDTLS_PK_WRAP_H -#define MBEDTLS_PK_WRAP_H - -#include "mbedtls/build_info.h" - -#include "mbedtls/pk.h" - -#if defined(MBEDTLS_PSA_CRYPTO_C) -#include "psa/crypto.h" -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -struct mbedtls_pk_info_t { - /** Public key type */ - mbedtls_pk_type_t type; - - /** Type name */ - const char *name; - - /** Get key size in bits */ - size_t (*get_bitlen)(mbedtls_pk_context *pk); - - /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ - int (*can_do)(mbedtls_pk_type_t type); - - /** Verify signature */ - int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len); - - /** Make signature */ - int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Verify signature (restartable) */ - int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len, - void *rs_ctx); - - /** Make signature (restartable) */ - int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, void *rs_ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - /** Decrypt message */ - int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - - /** Encrypt message */ - int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - - /** Check public-private key pair */ - int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - - /** Allocate a new context */ - void * (*ctx_alloc_func)(void); - - /** Free the given context */ - void (*ctx_free_func)(void *ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /** Allocate the restart context */ - void *(*rs_alloc_func)(void); - - /** Free the restart context */ - void (*rs_free_func)(void *rs_ctx); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - /** Interface with the debug module */ - void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items); - -}; -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Container for RSA-alt */ -typedef struct { - void *key; - mbedtls_pk_rsa_alt_decrypt_func decrypt_func; - mbedtls_pk_rsa_alt_sign_func sign_func; - mbedtls_pk_rsa_alt_key_len_func key_len_func; -} mbedtls_rsa_alt_context; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const mbedtls_pk_info_t mbedtls_rsa_info; -#endif - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -extern const mbedtls_pk_info_t mbedtls_eckey_info; -extern const mbedtls_pk_info_t mbedtls_eckeydh_info; -#endif - -#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) -extern const mbedtls_pk_info_t mbedtls_ecdsa_info; -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info; -extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info; - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) -int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status); -#endif -#endif - -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PSA_CRYPTO_C) -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status); - -#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) || \ - defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) -int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status); -#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#if defined(MBEDTLS_RSA_C) -int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md, - mbedtls_rsa_context *rsa_ctx, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, - size_t *sig_len); -#endif /* MBEDTLS_RSA_C */ - -#endif /* MBEDTLS_PSA_CRYPTO_C */ - -#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/matter/mbedtls/tinycrypt/src/pkparse.c b/matter/mbedtls/tinycrypt/src/pkparse.c deleted file mode 100644 index e1422df771..0000000000 --- a/matter/mbedtls/tinycrypt/src/pkparse.c +++ /dev/null @@ -1,1857 +0,0 @@ -/* - * Public Key layer for parsing key files and structures - * - * 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. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_PARSE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" -#include "pk_internal.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#include "mbedtls/ecp.h" -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#include "pk_internal.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PSA_CRYPTO_C) -#include "psa_util_internal.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#endif - -#include "mbedtls/platform.h" - -/* Helper for Montgomery curves */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) -#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \ - ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448)) -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && MBEDTLS_PK_HAVE_RFC8410_CURVES */ - -#if defined(MBEDTLS_FS_IO) -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n) -{ - FILE *f; - long size; - - if ((f = fopen(path, "rb")) == NULL) { - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - - /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ - mbedtls_setbuf(f, NULL); - - fseek(f, 0, SEEK_END); - if ((size = ftell(f)) == -1) { - fclose(f); - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - fseek(f, 0, SEEK_SET); - - *n = (size_t) size; - - if (*n + 1 == 0 || - (*buf = mbedtls_calloc(1, *n + 1)) == NULL) { - fclose(f); - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - if (fread(*buf, 1, *n, f) != *n) { - fclose(f); - - mbedtls_zeroize_and_free(*buf, *n); - - return MBEDTLS_ERR_PK_FILE_IO_ERROR; - } - - fclose(f); - - (*buf)[*n] = '\0'; - - if (strstr((const char *) *buf, "-----BEGIN ") != NULL) { - ++*n; - } - - return 0; -} - -/* - * Load and parse a private key - */ -int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, - const char *path, const char *pwd, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { - return ret; - } - - if (pwd == NULL) { - ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng); - } else { - ret = mbedtls_pk_parse_key(ctx, buf, n, - (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng); - } - - mbedtls_zeroize_and_free(buf, n); - - return ret; -} - -/* - * Load and parse a public key - */ -int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { - return ret; - } - - ret = mbedtls_pk_parse_public_key(ctx, buf, n); - - mbedtls_zeroize_and_free(buf, n); - - return ret; -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - * } - */ -static int pk_get_ecparams(unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (end - *p < 1) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_OUT_OF_DATA); - } - - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if (params->tag != MBEDTLS_ASN1_OID -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) -#endif - ) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); - } - - if ((ret = mbedtls_asn1_get_tag(p, end, ¶ms->len, params->tag)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - params->p = *p; - *p += params->len; - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. - * WARNING: the resulting group should only be used with - * pk_group_id_from_specified(), since its base point may not be set correctly - * if it was encoded compressed. - * - * SpecifiedECDomain ::= SEQUENCE { - * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), - * fieldID FieldID {{FieldTypes}}, - * curve Curve, - * base ECPoint, - * order INTEGER, - * cofactor INTEGER OPTIONAL, - * hash HashAlgorithm OPTIONAL, - * ... - * } - * - * We only support prime-field as field type, and ignore hash and cofactor. - */ -static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *p = params->p; - const unsigned char *const end = params->p + params->len; - const unsigned char *end_field, *end_curve; - size_t len; - int ver; - - /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ - if ((ret = mbedtls_asn1_get_int(&p, end, &ver)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (ver < 1 || ver > 3) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - /* - * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field - * fieldType FIELD-ID.&id({IOSet}), - * parameters FIELD-ID.&Type({IOSet}{@fieldType}) - * } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return ret; - } - - end_field = p + len; - - /* - * FIELD-ID ::= TYPE-IDENTIFIER - * FieldTypes FIELD-ID ::= { - * { Prime-p IDENTIFIED BY prime-field } | - * { Characteristic-two IDENTIFIED BY characteristic-two-field } - * } - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end_field, &len, MBEDTLS_ASN1_OID)) != 0) { - return ret; - } - - if (len != MBEDTLS_OID_SIZE(MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD) || - memcmp(p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len) != 0) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - - p += len; - - /* Prime-p ::= INTEGER -- Field of size p. */ - if ((ret = mbedtls_asn1_get_mpi(&p, end_field, &grp->P)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - grp->pbits = mbedtls_mpi_bitlen(&grp->P); - - if (p != end_field) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* - * Curve ::= SEQUENCE { - * a FieldElement, - * b FieldElement, - * seed BIT STRING OPTIONAL - * -- Shall be present if used in SpecifiedECDomain - * -- with version equal to ecdpVer2 or ecdpVer3 - * } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return ret; - } - - end_curve = p + len; - - /* - * FieldElement ::= OCTET STRING - * containing an integer in the case of a prime field - */ - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || - (ret = mbedtls_mpi_read_binary(&grp->A, p, len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - p += len; - - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0 || - (ret = mbedtls_mpi_read_binary(&grp->B, p, len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - p += len; - - /* Ignore seed BIT STRING OPTIONAL */ - if ((ret = mbedtls_asn1_get_tag(&p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING)) == 0) { - p += len; - } - - if (p != end_curve) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* - * ECPoint ::= OCTET STRING - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if ((ret = mbedtls_ecp_point_read_binary(grp, &grp->G, - (const unsigned char *) p, len)) != 0) { - /* - * If we can't read the point because it's compressed, cheat by - * reading only the X coordinate and the parity bit of Y. - */ - if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || - (p[0] != 0x02 && p[0] != 0x03) || - len != mbedtls_mpi_size(&grp->P) + 1 || - mbedtls_mpi_read_binary(&grp->G.X, p + 1, len - 1) != 0 || - mbedtls_mpi_lset(&grp->G.Y, p[0] - 2) != 0 || - mbedtls_mpi_lset(&grp->G.Z, 1) != 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - } - - p += len; - - /* - * order INTEGER - */ - if ((ret = mbedtls_asn1_get_mpi(&p, end, &grp->N)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - grp->nbits = mbedtls_mpi_bitlen(&grp->N); - - /* - * Allow optional elements by purposefully not enforcing p == end here. - */ - - return 0; -} - -/* - * Find the group id associated with an (almost filled) group as generated by - * pk_group_from_specified(), or return an error if unknown. - */ -static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id) -{ - int ret = 0; - mbedtls_ecp_group ref; - const mbedtls_ecp_group_id *id; - - mbedtls_ecp_group_init(&ref); - - for (id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++) { - /* Load the group associated to that id */ - mbedtls_ecp_group_free(&ref); - MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ref, *id)); - - /* Compare to the group we were given, starting with easy tests */ - if (grp->pbits == ref.pbits && grp->nbits == ref.nbits && - mbedtls_mpi_cmp_mpi(&grp->P, &ref.P) == 0 && - mbedtls_mpi_cmp_mpi(&grp->A, &ref.A) == 0 && - mbedtls_mpi_cmp_mpi(&grp->B, &ref.B) == 0 && - mbedtls_mpi_cmp_mpi(&grp->N, &ref.N) == 0 && - mbedtls_mpi_cmp_mpi(&grp->G.X, &ref.G.X) == 0 && - mbedtls_mpi_cmp_mpi(&grp->G.Z, &ref.G.Z) == 0 && - /* For Y we may only know the parity bit, so compare only that */ - mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) { - break; - } - } - -cleanup: - mbedtls_ecp_group_free(&ref); - - *grp_id = *id; - - if (ret == 0 && *id == MBEDTLS_ECP_DP_NONE) { - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - - return ret; -} - -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID - */ -static int pk_group_id_from_specified(const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_group grp; - - mbedtls_ecp_group_init(&grp); - - if ((ret = pk_group_from_specified(params, &grp)) != 0) { - goto cleanup; - } - - ret = pk_group_id_from_group(&grp, grp_id); - -cleanup: - /* The API respecting lifecycle for mbedtls_ecp_group struct is - * _init(), _load() and _free(). In pk_group_id_from_specified() the - * temporary grp breaks that flow and it's members are populated - * by pk_group_id_from_group(). As such mbedtls_ecp_group_free() - * which is assuming a group populated by _setup() may not clean-up - * properly -> Manually free it's members. - */ - mbedtls_mpi_free(&grp.N); - mbedtls_mpi_free(&grp.P); - mbedtls_mpi_free(&grp.A); - mbedtls_mpi_free(&grp.B); - mbedtls_ecp_point_free(&grp.G); - - return ret; -} -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -/* Functions pk_use_ecparams() and pk_use_ecparams_rfc8410() update the - * ecp_keypair structure with proper group ID. The purpose of this helper - * function is to update ec_family and ec_bits accordingly. */ -static int pk_update_psa_ecparams(mbedtls_pk_context *pk, - mbedtls_ecp_group_id grp_id) -{ - psa_ecc_family_t ec_family; - size_t bits; - - ec_family = mbedtls_ecc_group_to_psa(grp_id, &bits); - - if ((pk->ec_family != 0) && (pk->ec_family != ec_family)) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - pk->ec_family = ec_family; - pk->ec_bits = bits; - - return 0; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - -/* - * Use EC parameters to initialise an EC group - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - */ -static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_group_id grp_id; - - if (params->tag == MBEDTLS_ASN1_OID) { - if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) { - return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE; - } - } else { -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) { - return ret; - } -#else - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; -#endif - } - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - ret = pk_update_psa_ecparams(pk, grp_id); -#else - /* grp may already be initialized; if so, make sure IDs match */ - if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE && - mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - if ((ret = mbedtls_ecp_group_load(&(mbedtls_pk_ec_rw(*pk)->grp), - grp_id)) != 0) { - return ret; - } -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - return ret; -} - -/* - * Helper function for deriving a public key from its private counterpart. - */ -static int pk_derive_public_key(mbedtls_pk_context *pk, - const unsigned char *d, size_t d_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_status_t status; - (void) f_rng; - (void) p_rng; -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - (void) d; - (void) d_len; - - status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw), - &pk->pub_raw_len); - ret = psa_pk_status_to_mbedtls(status); -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; - unsigned char key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; - size_t key_len; - mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT; - psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - size_t curve_bits; - psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits); - psa_status_t destruction_status; - - psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve)); - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT); - - status = psa_import_key(&key_attr, d, d_len, &key_id); - ret = psa_pk_status_to_mbedtls(status); - if (ret != 0) { - return ret; - } - - status = psa_export_public_key(key_id, key_buf, sizeof(key_buf), &key_len); - ret = psa_pk_status_to_mbedtls(status); - destruction_status = psa_destroy_key(key_id); - if (ret != 0) { - return ret; - } else if (destruction_status != PSA_SUCCESS) { - return psa_pk_status_to_mbedtls(destruction_status); - } - ret = mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, key_buf, key_len); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -#else /* MBEDTLS_USE_PSA_CRYPTO */ - mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx; - (void) d; - (void) d_len; - - ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - return ret; -} - -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - -/* - * Load an RFC8410 EC key, which doesn't have any parameters - */ -static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id grp_id, - mbedtls_pk_context *pk) -{ - int ret; - - if (params->tag != 0 || params->len != 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - ret = pk_update_psa_ecparams(pk, grp_id); -#else - mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk); - ret = mbedtls_ecp_group_load(&(ecp->grp), grp_id); - if (ret != 0) { - return ret; - } -#endif - return ret; -} - -/* - * Parse an RFC 8410 encoded private EC key - * - * CurvePrivateKey ::= OCTET STRING - */ -static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk, - unsigned char *key, size_t keylen, const unsigned char *end, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (key + len != end) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; - - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT | - PSA_KEY_USAGE_DERIVE); - psa_set_key_algorithm(&attributes, PSA_ALG_ECDH); - - status = psa_import_key(&attributes, key, len, &pk->priv_id); - if (status != PSA_SUCCESS) { - ret = psa_pk_status_to_mbedtls(status); - return ret; - } -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); - - if ((ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys, - * which never contain a public key. As such, derive the public key - * unconditionally. */ - if ((ret = pk_derive_public_key(pk, key, len, f_rng, p_rng)) != 0) { - return ret; - } - - return 0; -} -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) && defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) -/* - * Create a temporary ecp_keypair for converting an EC point in compressed - * format to an uncompressed one - */ -static int pk_convert_compressed_ec(mbedtls_pk_context *pk, - const unsigned char *in_start, size_t in_len, - size_t *out_buf_len, unsigned char *out_buf, - size_t out_buf_size) -{ - mbedtls_ecp_keypair ecp_key; - mbedtls_ecp_group_id ecp_group_id; - int ret; - - ecp_group_id = mbedtls_ecc_group_of_psa(pk->ec_family, pk->ec_bits, 0); - - mbedtls_ecp_keypair_init(&ecp_key); - ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id); - if (ret != 0) { - return ret; - } - ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q, - in_start, in_len); - if (ret != 0) { - goto exit; - } - ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - out_buf_len, out_buf, out_buf_size); - -exit: - mbedtls_ecp_keypair_free(&ecp_key); - return ret; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA && MBEDTLS_PK_PARSE_EC_COMPRESSED */ - -/* - * EC public key is an EC point - * - * The caller is responsible for clearing the structure upon failure if - * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE - * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. - */ -static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - mbedtls_svc_key_id_t key; - psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; - size_t len = (end - *p); - - if (len > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* Compressed point format are not supported yet by PSA crypto. As a - * consequence ecp functions are used to "convert" the point to - * uncompressed format */ - if ((**p == 0x02) || (**p == 0x03)) { -#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) - ret = pk_convert_compressed_ec(pk, *p, len, - &(pk->pub_raw_len), pk->pub_raw, - PSA_EXPORT_PUBLIC_KEY_MAX_SIZE); - if (ret != 0) { - return ret; - } -#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */ - } else { - /* Uncompressed format */ - if ((size_t) (end - *p) > MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN) { - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; - } - memcpy(pk->pub_raw, *p, (end - *p)); - pk->pub_raw_len = end - *p; - } - - /* Validate the key by trying to importing it */ - psa_set_key_usage_flags(&key_attrs, 0); - psa_set_key_algorithm(&key_attrs, PSA_ALG_ECDSA_ANY); - psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)); - psa_set_key_bits(&key_attrs, pk->ec_bits); - - if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len, - &key) != PSA_SUCCESS) || - (psa_destroy_key(key) != PSA_SUCCESS)) { - mbedtls_platform_zeroize(pk->pub_raw, MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN); - pk->pub_raw_len = 0; - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - ret = 0; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx; - if ((ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, - (const unsigned char *) *p, - end - *p)) == 0) { - ret = mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q); - } -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *) end; - - return ret; -} -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_get_rsapubkey(unsigned char **p, - const unsigned char *end, - mbedtls_rsa_context *rsa) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if (*p + len != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* Import N */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0, - NULL, 0, NULL, 0)) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; - } - - *p += len; - - /* Import E */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0, - NULL, 0, *p, len)) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; - } - - *p += len; - - if (mbedtls_rsa_complete(rsa) != 0 || - mbedtls_rsa_check_pubkey(rsa) != 0) { - return MBEDTLS_ERR_PK_INVALID_PUBKEY; - } - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} -#endif /* MBEDTLS_RSA_C */ - -/* Get a PK algorithm identifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -static int pk_get_pk_alg(unsigned char **p, - const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *ec_grp_id) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_asn1_buf alg_oid; - - memset(params, 0, sizeof(mbedtls_asn1_buf)); - - if ((ret = mbedtls_asn1_get_alg(p, end, &alg_oid, params)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret); - } - - ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg); -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { - ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id); - if (ret == 0) { - *pk_alg = MBEDTLS_PK_ECKEY; - } - } -#else - (void) ec_grp_id; -#endif - if (ret != 0) { - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - } - - /* - * No parameters with RSA (only for EC) - */ - if (*pk_alg == MBEDTLS_PK_RSA && - ((params->tag != MBEDTLS_ASN1_NULL && params->tag != 0) || - params->len != 0)) { - return MBEDTLS_ERR_PK_INVALID_ALG; - } - - return 0; -} - -/* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ -int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - mbedtls_asn1_buf alg_params; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; - const mbedtls_pk_info_t *pk_info; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = *p + len; - - if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) { - return ret; - } - - if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret); - } - - if (*p + len != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - } - - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { - return ret; - } - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA) { - ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk)); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) { -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { - ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk); - } else -#endif - { - ret = pk_use_ecparams(&alg_params, pk); - } - if (ret == 0) { - ret = pk_get_ecpubkey(p, end, pk); - } - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - - if (ret == 0 && *p != end) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - if (ret != 0) { - mbedtls_pk_free(pk); - } - - return ret; -} - -#if defined(MBEDTLS_RSA_C) -/* - * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. - * - * The value zero is: - * - never a valid value for an RSA parameter - * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). - * - * Since values can't be omitted in PKCS#1, passing a zero value to - * rsa_complete() would be incorrect, so reject zero values early. - */ -static int asn1_get_nonzero_mpi(unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X) -{ - int ret; - - ret = mbedtls_asn1_get_mpi(p, end, X); - if (ret != 0) { - return ret; - } - - if (mbedtls_mpi_cmp_int(X, 0) == 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - return 0; -} - -/* - * Parse a PKCS#1 encoded private RSA key - */ -static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa, - const unsigned char *key, - size_t keylen) -{ - int ret, version; - size_t len; - unsigned char *p, *end; - - mbedtls_mpi T; - mbedtls_mpi_init(&T); - - p = (unsigned char *) key; - end = p + keylen; - - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (version != 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; - } - - /* Import N */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL, - NULL, NULL)) != 0) { - goto cleanup; - } - - /* Import E */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, - NULL, &T)) != 0) { - goto cleanup; - } - - /* Import D */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL, - &T, NULL)) != 0) { - goto cleanup; - } - - /* Import P */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL, - NULL, NULL)) != 0) { - goto cleanup; - } - - /* Import Q */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T, - NULL, NULL)) != 0) { - goto cleanup; - } - -#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) - /* - * The RSA CRT parameters DP, DQ and QP are nominally redundant, in - * that they can be easily recomputed from D, P and Q. However by - * parsing them from the PKCS1 structure it is possible to avoid - * recalculating them which both reduces the overhead of loading - * RSA private keys into memory and also avoids side channels which - * can arise when computing those values, since all of D, P, and Q - * are secret. See https://eprint.iacr.org/2020/055 for a - * description of one such attack. - */ - - /* Import DP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) { - goto cleanup; - } - - /* Import DQ */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) { - goto cleanup; - } - - /* Import QP */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) { - goto cleanup; - } - -#else - /* Verify existence of the CRT params */ - if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 || - (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) { - goto cleanup; - } -#endif - - /* rsa_complete() doesn't complete anything with the default - * implementation but is still called: - * - for the benefit of alternative implementation that may want to - * pre-compute stuff beyond what's provided (eg Montgomery factors) - * - as is also sanity-checks the key - * - * Furthermore, we also check the public part for consistency with - * mbedtls_pk_parse_pubkey(), as it includes size minima for example. - */ - if ((ret = mbedtls_rsa_complete(rsa)) != 0 || - (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) { - goto cleanup; - } - - if (p != end) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - -cleanup: - - mbedtls_mpi_free(&T); - - if (ret != 0) { - /* Wrap error code if it's coming from a lower level */ - if ((ret & 0xff80) == 0) { - ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } else { - ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - - mbedtls_rsa_free(rsa); - } - - return ret; -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -/* - * Parse a SEC1 encoded private EC key - */ -static int pk_parse_key_sec1_der(mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int version, pubkey_done; - size_t len, d_len; - mbedtls_asn1_buf params = { 0, 0, NULL }; - unsigned char *p = (unsigned char *) key; - unsigned char *d; - unsigned char *end = p + keylen; - unsigned char *end2; -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ - mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk); -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (version != 1) { - return MBEDTLS_ERR_PK_KEY_INVALID_VERSION; - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - /* Keep a reference to the position fo the private key. It will be used - * later in this function. */ - d = p; - d_len = len; - - p += len; - - pubkey_done = 0; - if (p != end) { - /* - * Is 'parameters' present? - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | - 0)) == 0) { - if ((ret = pk_get_ecparams(&p, p + len, ¶ms)) != 0 || - (ret = pk_use_ecparams(¶ms, pk)) != 0) { - return ret; - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - } - - -#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA) - if ((ret = mbedtls_ecp_read_key(eck->grp.id, eck, d, d_len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } -#endif - - if (p != end) { - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | - 1)) == 0) { - end2 = p + len; - - if ((ret = mbedtls_asn1_get_bitstring_null(&p, end2, &len)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (p + len != end2) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - if ((ret = pk_get_ecpubkey(&p, end2, pk)) == 0) { - pubkey_done = 1; - } else { - /* - * The only acceptable failure mode of pk_get_ecpubkey() above - * is if the point format is not recognized. - */ - if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - } - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - } - -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) - psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family)); - /* Setting largest masks for usage and key algorithms */ - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | - PSA_KEY_USAGE_SIGN_MESSAGE | - PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE); -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - psa_set_key_algorithm(&attributes, - PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH)); -#else - psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)); -#endif - psa_set_key_enrollment_algorithm(&attributes, PSA_ALG_ECDH); - - status = psa_import_key(&attributes, d, d_len, &pk->priv_id); - if (status != PSA_SUCCESS) { - ret = psa_pk_status_to_mbedtls(status); - return ret; - } -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - - if (!pubkey_done) { - if ((ret = pk_derive_public_key(pk, d, d_len, f_rng, p_rng)) != 0) { - return ret; - } - } - - return 0; -} -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -/* - * Parse an unencrypted PKCS#8 encoded private key - * - * Notes: - * - * - This function does not own the key buffer. It is the - * responsibility of the caller to take care of zeroizing - * and freeing it after use. - * - * - The function is responsible for freeing the provided - * PK context on failure. - * - */ -static int pk_parse_key_pkcs8_unencrypted_der( - mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret, version; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; - const mbedtls_pk_info_t *pk_info; - -#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) - (void) f_rng; - (void) p_rng; -#endif - - /* - * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey - */ - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (version != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret); - } - - if ((ret = pk_get_pk_alg(&p, end, &pk_alg, ¶ms, &ec_grp_id)) != 0) { - return ret; - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if (len < 1) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_OUT_OF_DATA); - } - - if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) { - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - } - - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0) { - return ret; - } - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA) { - if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) { - mbedtls_pk_free(pk); - return ret; - } - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) { -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) { - if ((ret = - pk_use_ecparams_rfc8410(¶ms, ec_grp_id, pk)) != 0 || - (ret = - pk_parse_key_rfc8410_der(pk, p, len, end, f_rng, - p_rng)) != 0) { - mbedtls_pk_free(pk); - return ret; - } - } else -#endif - { - if ((ret = pk_use_ecparams(¶ms, pk)) != 0 || - (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) { - mbedtls_pk_free(pk); - return ret; - } - } - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - - end = p + len; - if (end != (key + keylen)) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * Parse an encrypted PKCS#8 encoded private key - * - * To save space, the decryption happens in-place on the given key buffer. - * Also, while this function may modify the keybuffer, it doesn't own it, - * and instead it is the responsibility of the caller to zeroize and properly - * free it after use. - * - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der( - mbedtls_pk_context *pk, - unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret, decrypted = 0; - size_t len; - unsigned char *buf; - unsigned char *p, *end; - mbedtls_asn1_buf pbe_alg_oid, pbe_params; -#if defined(MBEDTLS_PKCS12_C) - mbedtls_cipher_type_t cipher_alg; - mbedtls_md_type_t md_alg; -#endif - size_t outlen = 0; - - p = key; - end = p + keylen; - - if (pwdlen == 0) { - return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; - } - - /* - * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData - * } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - * - * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo - * - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - end = p + len; - - if ((ret = mbedtls_asn1_get_alg(&p, end, &pbe_alg_oid, &pbe_params)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret); - } - - buf = p; - - /* - * Decrypt EncryptedData with appropriate PBE - */ -#if defined(MBEDTLS_PKCS12_C) - if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) { - if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, - pwd, pwdlen, p, len, buf, len, &outlen)) != 0) { - if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) { - return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } - - return ret; - } - - decrypted = 1; - } else -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PKCS5_C) - if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) { - if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, - p, len, buf, len, &outlen)) != 0) { - if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) { - return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } - - return ret; - } - - decrypted = 1; - } else -#endif /* MBEDTLS_PKCS5_C */ - { - ((void) pwd); - } - - if (decrypted == 0) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng); -} -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - -/* - * Parse a private key - */ -int mbedtls_pk_parse_key(mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const mbedtls_pk_info_t *pk_info; -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; -#endif - - if (keylen == 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init(&pem); - -#if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len); - } - - if (ret == 0) { - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), - pem.buf, pem.buflen)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return ret; - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { - return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { - return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - return ret; - } -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", - key, pwd, pwdlen, &len); - } - if (ret == 0) { - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - - if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 || - (ret = pk_parse_key_sec1_der(pk, - pem.buf, pem.buflen, - f_rng, p_rng)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return ret; - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) { - return MBEDTLS_ERR_PK_PASSWORD_MISMATCH; - } else if (ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) { - return MBEDTLS_ERR_PK_PASSWORD_REQUIRED; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - return ret; - } -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, NULL, 0, &len); - } - if (ret == 0) { - if ((ret = pk_parse_key_pkcs8_unencrypted_der(pk, - pem.buf, pem.buflen, f_rng, p_rng)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return ret; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - return ret; - } - -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", - key, NULL, 0, &len); - } - if (ret == 0) { - if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen, - pwd, pwdlen, f_rng, p_rng)) != 0) { - mbedtls_pk_free(pk); - } - - mbedtls_pem_free(&pem); - return ret; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - return ret; - } -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ -#else - ((void) pwd); - ((void) pwdlen); -#endif /* MBEDTLS_PEM_PARSE_C */ - - /* - * At this point we only know it's not a PEM formatted key. Could be any - * of the known DER encoded private key formats - * - * We try the different DER format parsers to see if one passes without - * error - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - if (pwdlen != 0) { - unsigned char *key_copy; - - if ((key_copy = mbedtls_calloc(1, keylen)) == NULL) { - return MBEDTLS_ERR_PK_ALLOC_FAILED; - } - - memcpy(key_copy, key, keylen); - - ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen, - pwd, pwdlen, f_rng, p_rng); - - mbedtls_zeroize_and_free(key_copy, keylen); - } - - if (ret == 0) { - return 0; - } - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - - if (ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH) { - return ret; - } -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - - ret = pk_parse_key_pkcs8_unencrypted_der(pk, key, keylen, f_rng, p_rng); - if (ret == 0) { - return 0; - } - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); - -#if defined(MBEDTLS_RSA_C) - - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA); - if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) { - return 0; - } - - mbedtls_pk_free(pk); - mbedtls_pk_init(pk); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); - if (mbedtls_pk_setup(pk, pk_info) == 0 && - pk_parse_key_sec1_der(pk, - key, keylen, f_rng, p_rng) == 0) { - return 0; - } - mbedtls_pk_free(pk); -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - - /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't, - * it is ok to leave the PK context initialized but not - * freed: It is the caller's responsibility to call pk_init() - * before calling this function, and to call pk_free() - * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C - * isn't, this leads to mbedtls_pk_free() being called - * twice, once here and once by the caller, but this is - * also ok and in line with the mbedtls_pk_free() calls - * on failed PEM parsing attempts. */ - - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; -} - -/* - * Parse a public key - */ -int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *p; -#if defined(MBEDTLS_RSA_C) - const mbedtls_pk_info_t *pk_info; -#endif -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; -#endif - - if (keylen == 0) { - return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; - } - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init(&pem); -#if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN RSA PUBLIC KEY-----", - "-----END RSA PUBLIC KEY-----", - key, NULL, 0, &len); - } - - if (ret == 0) { - p = pem.buf; - if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { - mbedtls_pem_free(&pem); - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - } - - if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { - mbedtls_pem_free(&pem); - return ret; - } - - if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) { - mbedtls_pk_free(ctx); - } - - mbedtls_pem_free(&pem); - return ret; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - return ret; - } -#endif /* MBEDTLS_RSA_C */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if (key[keylen - 1] != '\0') { - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - } else { - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len); - } - - if (ret == 0) { - /* - * Was PEM encoded - */ - p = pem.buf; - - ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx); - mbedtls_pem_free(&pem); - return ret; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - return ret; - } - mbedtls_pem_free(&pem); -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_RSA_C) - if ((pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == NULL) { - return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - } - - if ((ret = mbedtls_pk_setup(ctx, pk_info)) != 0) { - return ret; - } - - p = (unsigned char *) key; - ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx)); - if (ret == 0) { - return ret; - } - mbedtls_pk_free(ctx); - if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) { - return ret; - } -#endif /* MBEDTLS_RSA_C */ - p = (unsigned char *) key; - - ret = mbedtls_pk_parse_subpubkey(&p, p + keylen, ctx); - - return ret; -} - -#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/pkwrite.c b/matter/mbedtls/tinycrypt/src/pkwrite.c deleted file mode 100644 index 03db1454aa..0000000000 --- a/matter/mbedtls/tinycrypt/src/pkwrite.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Public Key layer for writing key files and structures - * - * 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. - */ - -#include "common.h" - -#if defined(MBEDTLS_PK_WRITE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/error.h" -#include "pk_internal.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/bignum.h" -#include "mbedtls/ecp.h" -#include "mbedtls/platform_util.h" -#endif -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#include "pk_internal.h" -#endif -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#include "pkwrite.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#include "psa_util_internal.h" -#endif -#include "mbedtls/platform.h" - -/* Helper for Montgomery curves */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) -static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk) -{ - mbedtls_ecp_group_id id = mbedtls_pk_get_group_id(pk); - -#if defined(MBEDTLS_ECP_HAVE_CURVE25519) - if (id == MBEDTLS_ECP_DP_CURVE25519) { - return 1; - } -#endif -#if defined(MBEDTLS_ECP_HAVE_CURVE448) - if (id == MBEDTLS_ECP_DP_CURVE448) { - return 1; - } -#endif - return 0; -} - -#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PEM_WRITE_C) -/* It is assumed that the input key is opaque */ -static psa_ecc_family_t pk_get_opaque_ec_family(const mbedtls_pk_context *pk) -{ - psa_ecc_family_t ec_family = 0; - psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT; - - if (psa_get_key_attributes(pk->priv_id, &key_attrs) != PSA_SUCCESS) { - return 0; - } - ec_family = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attrs)); - psa_reset_key_attributes(&key_attrs); - - return ec_family; -} -#endif /* MBETLS_USE_PSA_CRYPTO && MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* It is assumed that the input key is opaque */ -static psa_key_type_t pk_get_opaque_key_type(const mbedtls_pk_context *pk) -{ - psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT; - psa_key_type_t opaque_key_type; - - if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) { - return 0; - } - opaque_key_type = psa_get_key_type(&opaque_attrs); - psa_reset_key_attributes(&opaque_attrs); - - return opaque_key_type; -} -#endif /* MBETLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - mbedtls_mpi T; - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); - - mbedtls_mpi_init(&T); - - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) { - goto end_of_export; - } - len += ret; - -end_of_export: - - mbedtls_mpi_free(&T); - if (ret < 0) { - return ret; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return (int) len; -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - size_t len = 0; - uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; - - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { - if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - } else { - len = pk->pub_raw_len; - memcpy(buf, pk->pub_raw, len); - } - - if (*p < start || (size_t) (*p - start) < len) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - *p -= len; - memcpy(*p, buf, len); - - return (int) len; -} -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - size_t len = 0; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - uint8_t buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; -#else - unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk); - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { - if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - *p -= len; - memcpy(*p, buf, len); - return (int) len; - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - { - if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &len, buf, sizeof(buf))) != 0) { - return ret; - } - } - - if (*p < start || (size_t) (*p - start) < len) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - *p -= len; - memcpy(*p, buf, len); - - return (int) len; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ - -/* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * } - */ -static int pk_write_ec_param(unsigned char **p, unsigned char *start, - mbedtls_ecp_group_id grp_id) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - const char *oid; - size_t oid_len; - - if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) { - return ret; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); - - return (int) len; -} - -/* - * privateKey OCTET STRING -- always of length ceil(log2(n)/8) - */ -#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) -static int pk_write_ec_private(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - size_t byte_length; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - psa_status_t status; - - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { - status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); - if (status != PSA_SUCCESS) { - ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - return ret; - } - } else { - status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); - if (status != PSA_SUCCESS) { - ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - goto exit; - } - } - - ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); -exit: - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - return ret; -} -#else /* MBEDTLS_PK_USE_PSA_EC_DATA */ -static int pk_write_ec_private(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - size_t byte_length; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - unsigned char tmp[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH]; - psa_status_t status; -#else - unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { - status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length); - if (status != PSA_SUCCESS) { - ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status); - return ret; - } - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - { - mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk); - byte_length = (ec->grp.pbits + 7) / 8; - - ret = mbedtls_ecp_write_key(ec, tmp, byte_length); - if (ret != 0) { - goto exit; - } - } - ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length); -exit: - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - return ret; -} -#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */ -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *pk) -{ - size_t buffer_size; - size_t len = 0; - - if (*p < start) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - buffer_size = (size_t) (*p - start); - if (psa_export_public_key(pk->priv_id, start, buffer_size, - &len) != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - *p -= len; - memmove(*p, start, len); - - return (int) len; -} -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - -#if defined(MBEDTLS_RSA_C) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) { - MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key)); - } else -#endif -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key)); - } else -#endif -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { - MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key)); - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - - return (int) len; -} - -int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char *c; - int has_par = 1; - size_t len = 0, par_len = 0, oid_len = 0; - mbedtls_pk_type_t pk_type; -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE; -#endif - const char *oid = NULL; - - if (size == 0) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key)); - - if (c - buf < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ - *--c = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); - - pk_type = mbedtls_pk_get_type(key); -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (pk_type == MBEDTLS_PK_ECKEY) { - ec_grp_id = mbedtls_pk_get_group_id(key); - } -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (pk_type == MBEDTLS_PK_OPAQUE) { - psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key); -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) { - pk_type = MBEDTLS_PK_ECKEY; - ec_grp_id = mbedtls_pk_get_group_id(key); - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) { - /* The rest of the function works as for legacy RSA contexts. */ - pk_type = MBEDTLS_PK_RSA; - } - } - /* `pk_type` will have been changed to non-opaque by here if this function can handle it */ - if (pk_type == MBEDTLS_PK_OPAQUE) { - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (pk_type == MBEDTLS_PK_ECKEY) { - /* Some groups have their own AlgorithmIdentifier OID, others are handled - * by mbedtls_oid_get_oid_by_pk_alg() below */ - ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len); - - if (ret == 0) { - /* Currently, none of the supported algorithms that have their own - * AlgorithmIdentifier OID have any parameters */ - has_par = 0; - } else if (ret == MBEDTLS_ERR_OID_NOT_FOUND) { - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id)); - } else { - return ret; - } - } -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - - if (oid_len == 0) { - if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, - &oid_len)) != 0) { - return ret; - } - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len, - par_len, has_par)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return (int) len; -} - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) -/* - * RFC8410 section 7 - * - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], - * ... - * } - * ... - * CurvePrivateKey ::= OCTET STRING - */ -static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf, - const mbedtls_pk_context *pk) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0; - size_t oid_len = 0; - const char *oid; - mbedtls_ecp_group_id grp_id; - - /* privateKey */ - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING)); - - grp_id = mbedtls_pk_get_group_id(pk); - /* privateKeyAlgorithm */ - if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) { - return ret; - } - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0)); - - /* version */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return (int) len; -} -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ - -/* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ -static int pk_write_ec_der(unsigned char **p, unsigned char *buf, - const mbedtls_pk_context *pk) -{ - size_t len = 0; - int ret; - size_t pub_len = 0, par_len = 0; - mbedtls_ecp_group_id grp_id; - - /* publicKey */ - MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk)); - - if (*p - buf < 1) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - (*p)--; - **p = 0; - pub_len += 1; - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING)); - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len)); - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 1)); - len += pub_len; - - /* parameters */ - grp_id = mbedtls_pk_get_group_id(pk); - MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id)); - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len)); - MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0)); - len += par_len; - - /* privateKey */ - MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk)); - - /* version */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - return (int) len; -} -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - -#if defined(MBEDTLS_RSA_C) -static int pk_write_rsa_der(unsigned char **p, unsigned char *buf, - const mbedtls_pk_context *pk) -{ - size_t len = 0; - int ret; - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) { - uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE]; - size_t tmp_len = 0; - - if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - *p -= tmp_len; - memcpy(*p, tmp, tmp_len); - len += tmp_len; - mbedtls_platform_zeroize(tmp, sizeof(tmp)); - } else -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - { - mbedtls_mpi T; /* Temporary holding the exported parameters */ - mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk); - - /* - * Export the parameters one after another to avoid simultaneous copies. - */ - - mbedtls_mpi_init(&T); - - /* Export QP */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export DQ */ - if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export DP */ - if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export Q */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - &T, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export P */ - if ((ret = mbedtls_rsa_export(rsa, NULL, &T, - NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export D */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - NULL, &T, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export E */ - if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, - NULL, NULL, &T)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - - /* Export N */ - if ((ret = mbedtls_rsa_export(rsa, &T, NULL, - NULL, NULL, NULL)) != 0 || - (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) { - goto end_of_export; - } - len += ret; - -end_of_export: - - mbedtls_mpi_free(&T); - if (ret < 0) { - return ret; - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, - buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - } - - return (int) len; -} -#endif /* MBEDTLS_RSA_C */ - -int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size) -{ - unsigned char *c; -#if defined(MBEDTLS_RSA_C) - int is_rsa_opaque = 0; -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - int is_ec_opaque = 0; -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_key_type_t opaque_key_type; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - if (size == 0) { - return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; - } - - c = buf + size; - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { - opaque_key_type = pk_get_opaque_key_type(key); -#if defined(MBEDTLS_RSA_C) - is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type); -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type); -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_RSA_C) - if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) { - return pk_write_rsa_der(&c, buf, key); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) { -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - if (mbedtls_pk_is_rfc8410(key)) { - return pk_write_ec_rfc8410_der(&c, buf, key); - } -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ - return pk_write_ec_der(&c, buf, key); - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; -} - -#if defined(MBEDTLS_PEM_WRITE_C) - -#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" -#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" - -#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----\n" - -#define PUB_DER_MAX_BYTES \ - (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \ - MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES) -#define PRV_DER_MAX_BYTES \ - (MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \ - MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES) - -int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PUB_DER_MAX_BYTES]; - size_t olen = 0; - - if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf, - sizeof(output_buf))) < 0) { - return ret; - } - - if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen)) != 0) { - return ret; - } - - return 0; -} - -int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned char output_buf[PRV_DER_MAX_BYTES]; - const char *begin, *end; - size_t olen = 0; -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - int is_ec_opaque = 0; -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - int is_montgomery_opaque = 0; -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#if defined(MBEDTLS_RSA_C) - int is_rsa_opaque = 0; -#endif - - if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { - return ret; - } - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) { - psa_key_type_t opaque_key_type = pk_get_opaque_key_type(key); - -#if defined(MBEDTLS_RSA_C) - is_rsa_opaque = PSA_KEY_TYPE_IS_RSA(opaque_key_type); -#endif -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - is_ec_opaque = PSA_KEY_TYPE_IS_ECC(opaque_key_type); -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - if (pk_get_opaque_ec_family(key) == PSA_ECC_FAMILY_MONTGOMERY) { - is_montgomery_opaque = 1; - } -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#if defined(MBEDTLS_RSA_C) - if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) || is_rsa_opaque) { - begin = PEM_BEGIN_PRIVATE_KEY_RSA; - end = PEM_END_PRIVATE_KEY_RSA; - } else -#endif -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) || is_ec_opaque) { -#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES) - if (is_montgomery_opaque || - ((mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) && - (mbedtls_pk_is_rfc8410(key)))) { - begin = PEM_BEGIN_PRIVATE_KEY_PKCS8; - end = PEM_END_PRIVATE_KEY_PKCS8; - } else -#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */ - { - begin = PEM_BEGIN_PRIVATE_KEY_EC; - end = PEM_END_PRIVATE_KEY_EC; - } - } else -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - - if ((ret = mbedtls_pem_write_buffer(begin, end, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen)) != 0) { - return ret; - } - - return 0; -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c index b682394f7d..0a7fb83fa9 100644 --- a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c +++ b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c @@ -22,6 +22,8 @@ #include #include +#include + #include #if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) @@ -204,4 +206,53 @@ void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num) } mbedtls_platform_fault(); return NULL; +} + +int mbedtls_platform_memmove(void *dst, const void *src, size_t num) +{ + void *ret1 = NULL; + void *ret2 = NULL; + /* The buffers can have a common part, so we cannot do a copy from a random + * location. By using a temporary buffer we can do so, but the cost of it + * is using more memory and longer transfer time. */ + void *tmp = mbedtls_calloc(1, num); + if (tmp != NULL) { + ret1 = mbedtls_platform_memcpy(tmp, src, num); + ret2 = mbedtls_platform_memcpy(dst, tmp, num); + mbedtls_free(tmp); + if (ret1 == tmp && ret2 == dst) { + return 0; + } + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; +} + +int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num) +{ + volatile const unsigned char *A = (volatile const unsigned char *)buf1; + volatile const unsigned char *B = (volatile const unsigned char *)buf2; + volatile unsigned char diff = 0; + + /* Start from a random location and check the correct number of iterations */ + size_t i, flow_counter = 0; + size_t start_offset = 0; + if (num > 0) { + start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); + + for (i = start_offset; i < num; i++) { + unsigned char x = A[i], y = B[i]; + flow_counter++; + diff |= x ^ y; + } + + for (i = 0; i < start_offset; i++) { + unsigned char x = A[i], y = B[i]; + flow_counter++; + diff |= x ^ y; + } + } + /* Return 0 only when diff is 0 and flow_counter is equal to num */ + return ((int)diff | (int)(flow_counter ^ num)); } \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/utils.c b/matter/mbedtls/tinycrypt/src/utils.c deleted file mode 100644 index 13cc495123..0000000000 --- a/matter/mbedtls/tinycrypt/src/utils.c +++ /dev/null @@ -1,74 +0,0 @@ -/* utils.c - TinyCrypt platform-dependent run-time operations */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include - -#define MASK_TWENTY_SEVEN 0x1b - -unsigned int _copy(uint8_t *to, unsigned int to_len, - const uint8_t *from, unsigned int from_len) -{ - if (from_len <= to_len) { - (void)memcpy(to, from, from_len); - return from_len; - } else { - return TC_CRYPTO_FAIL; - } -} - -void _set(void *to, uint8_t val, unsigned int len) -{ - (void)memset(to, val, len); -} - -/* - * Doubles the value of a byte for values up to 127. - */ -uint8_t _double_byte(uint8_t a) -{ - return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN)); -} - -int _compare(const uint8_t *a, const uint8_t *b, size_t size) -{ - const uint8_t *tempa = a; - const uint8_t *tempb = b; - uint8_t result = 0; - - for (unsigned int i = 0; i < size; i++) { - result |= tempa[i] ^ tempb[i]; - } - return result; -} diff --git a/matter/mbedtls/tinycrypt/src/x509_crt.c b/matter/mbedtls/tinycrypt/src/x509_crt.c deleted file mode 100644 index 7a63140d6f..0000000000 --- a/matter/mbedtls/tinycrypt/src/x509_crt.c +++ /dev/null @@ -1,3308 +0,0 @@ -/* - * X.509 certificate parsing and verification - * - * 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. - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - * - * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf - */ - -#include "common.h" - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#include "psa_util_internal.h" -#include "md_psa.h" -#endif /* MBEDTLS_USE_PSA_CRYPTO */ -#include "pk_internal.h" - -#include "mbedtls/platform.h" - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#define WIN32_LEAN_AND_MEAN -#include -#else -#include -#endif -#endif - -#if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) -#if defined(MBEDTLS_FS_IO) -#include -#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) -#include -#include -#if defined(__MBED__) -#include -#else -#include -#endif /* __MBED__ */ -#include -#endif /* !_WIN32 || EFIX64 || EFI32 */ -#endif -#endif - -/* - * Item in a verification chain: cert and flags for it - */ -typedef struct { - mbedtls_x509_crt *crt; - uint32_t flags; -} x509_crt_verify_chain_item; - -/* - * Max size of verification chain: end-entity + intermediates + trusted root - */ -#define X509_MAX_VERIFY_CHAIN_SIZE (MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2) - -/* Default profile. Do not remove items unless there are serious security - * concerns. */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = -{ - /* Hashes from SHA-256 and above. Note that this selection - * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), - 0xFFFFFFF, /* Any PK alg */ -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - /* Curves at or above 128-bit security level. Note that this selection - * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | - 0, -#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ - 0, -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - 2048, -}; - -/* Next-generation profile. Currently identical to the default, but may - * be tightened at any time. */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = -{ - /* Hashes from SHA-256 and above. */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), - 0xFFFFFFF, /* Any PK alg */ -#if defined(MBEDTLS_ECP_C) - /* Curves at or above 128-bit security level. */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP521R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256K1), -#else - 0, -#endif - 2048, -}; - -/* - * NSA Suite B Profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = -{ - /* Only SHA-256 and 384 */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384), - /* Only ECDSA */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY), -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - /* Only NIST P-256 and P-384 */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), -#else /* MBEDTLS_PK_HAVE_ECC_KEYS */ - 0, -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - 0, -}; - -/* - * Empty / all-forbidden profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = -{ - 0, - 0, - 0, - (uint32_t) -1, -}; - -/* - * Check md_alg against profile - * Return 0 if md_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg) -{ - if (md_alg == MBEDTLS_MD_NONE) { - return -1; - } - - if ((profile->allowed_mds & MBEDTLS_X509_ID_FLAG(md_alg)) != 0) { - return 0; - } - - return -1; -} - -/* - * Check pk_alg against profile - * Return 0 if pk_alg is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg(const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg) -{ - if (pk_alg == MBEDTLS_PK_NONE) { - return -1; - } - - if ((profile->allowed_pks & MBEDTLS_X509_ID_FLAG(pk_alg)) != 0) { - return 0; - } - - return -1; -} - -/* - * Check key against profile - * Return 0 if pk is acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile, - const mbedtls_pk_context *pk) -{ - const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(pk); - -#if defined(MBEDTLS_RSA_C) - if (pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) { - if (mbedtls_pk_get_bitlen(pk) >= profile->rsa_min_bitlen) { - return 0; - } - - return -1; - } -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) - if (pk_alg == MBEDTLS_PK_ECDSA || - pk_alg == MBEDTLS_PK_ECKEY || - pk_alg == MBEDTLS_PK_ECKEY_DH) { - const mbedtls_ecp_group_id gid = mbedtls_pk_get_group_id(pk); - - if (gid == MBEDTLS_ECP_DP_NONE) { - return -1; - } - - if ((profile->allowed_curves & MBEDTLS_X509_ID_FLAG(gid)) != 0) { - return 0; - } - - return -1; - } -#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ - - return -1; -} - -/* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp(const void *s1, const void *s2, size_t len) -{ - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for (i = 0; i < len; i++) { - diff = n1[i] ^ n2[i]; - - if (diff == 0) { - continue; - } - - if (diff == 32 && - ((n1[i] >= 'a' && n1[i] <= 'z') || - (n1[i] >= 'A' && n1[i] <= 'Z'))) { - continue; - } - - return -1; - } - - return 0; -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard(const char *cn, const mbedtls_x509_buf *name) -{ - size_t i; - size_t cn_idx = 0, cn_len = strlen(cn); - - /* We can't have a match if there is no wildcard to match */ - if (name->len < 3 || name->p[0] != '*' || name->p[1] != '.') { - return -1; - } - - for (i = 0; i < cn_len; ++i) { - if (cn[i] == '.') { - cn_idx = i; - break; - } - } - - if (cn_idx == 0) { - return -1; - } - - if (cn_len - cn_idx == name->len - 1 && - x509_memcasecmp(name->p + 1, cn + cn_idx, name->len - 1) == 0) { - return 0; - } - - return -1; -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp(const mbedtls_x509_buf *a, const mbedtls_x509_buf *b) -{ - if (a->tag == b->tag && - a->len == b->len && - memcmp(a->p, b->p, b->len) == 0) { - return 0; - } - - if ((a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && - (b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING) && - a->len == b->len && - x509_memcasecmp(a->p, b->p, b->len) == 0) { - return 0; - } - - return -1; -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp(const mbedtls_x509_name *a, const mbedtls_x509_name *b) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while (a != NULL || b != NULL) { - if (a == NULL || b == NULL) { - return -1; - } - - /* type */ - if (a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp(a->oid.p, b->oid.p, b->oid.len) != 0) { - return -1; - } - - /* value */ - if (x509_string_cmp(&a->val, &b->val) != 0) { - return -1; - } - - /* structure of the list of sets */ - if (a->next_merged != b->next_merged) { - return -1; - } - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return 0; -} - -/* - * Reset (init or clear) a verify_chain - */ -static void x509_crt_verify_chain_reset( - mbedtls_x509_crt_verify_chain *ver_chain) -{ - size_t i; - - for (i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++) { - ver_chain->items[i].crt = NULL; - ver_chain->items[i].flags = (uint32_t) -1; - } - - ver_chain->len = 0; - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - ver_chain->trust_ca_cb_result = NULL; -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -} - -/* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ -static int x509_get_version(unsigned char **p, - const unsigned char *end, - int *ver) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | - 0)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - *ver = 0; - return 0; - } - - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); - } - - end = *p + len; - - if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret); - } - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ -static int x509_get_dates(unsigned char **p, - const unsigned char *end, - mbedtls_x509_time *from, - mbedtls_x509_time *to) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); - } - - end = *p + len; - - if ((ret = mbedtls_x509_get_time(p, end, from)) != 0) { - return ret; - } - - if ((ret = mbedtls_x509_get_time(p, end, to)) != 0) { - return ret; - } - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * X.509 v2/v3 unique identifier (not parsed) - */ -static int x509_get_uid(unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *uid, int n) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if (*p == end) { - return 0; - } - - uid->tag = **p; - - if ((ret = mbedtls_asn1_get_tag(p, end, &uid->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | - n)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return 0; - } - - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); - } - - uid->p = *p; - *p += uid->len; - - return 0; -} - -static int x509_get_basic_constraints(unsigned char **p, - const unsigned char *end, - int *ca_istrue, - int *max_pathlen) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - *ca_istrue = 0; /* DEFAULT FALSE */ - *max_pathlen = 0; /* endless */ - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*p == end) { - return 0; - } - - if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { - if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - ret = mbedtls_asn1_get_int(p, end, ca_istrue); - } - - if (ret != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*ca_istrue != 0) { - *ca_istrue = 1; - } - } - - if (*p == end) { - return 0; - } - - if ((ret = mbedtls_asn1_get_int(p, end, max_pathlen)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer - * overflow, which is an undefined behavior. */ - if (*max_pathlen == INT_MAX) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH); - } - - (*max_pathlen)++; - - return 0; -} - -/* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - * - * KeyPurposeId ::= OBJECT IDENTIFIER - */ -static int x509_get_ext_key_usage(unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *ext_key_usage) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - if ((ret = mbedtls_asn1_get_sequence_of(p, end, ext_key_usage, MBEDTLS_ASN1_OID)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - /* Sequence length must be >= 1 */ - if (ext_key_usage->buf.p == NULL) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_INVALID_LENGTH); - } - - return 0; -} - -/* - * SubjectKeyIdentifier ::= KeyIdentifier - * - * KeyIdentifier ::= OCTET STRING - */ -static int x509_get_subject_key_id(unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *subject_key_id) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0u; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - subject_key_id->len = len; - subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING; - subject_key_id->p = *p; - *p += len; - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * AuthorityKeyIdentifier ::= SEQUENCE { - * keyIdentifier [0] KeyIdentifier OPTIONAL, - * authorityCertIssuer [1] GeneralNames OPTIONAL, - * authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } - * - * KeyIdentifier ::= OCTET STRING - */ -static int x509_get_authority_key_id(unsigned char **p, - unsigned char *end, - mbedtls_x509_authority *authority_key_id) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len = 0u; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*p + len != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC); - - /* KeyIdentifier is an OPTIONAL field */ - if (ret == 0) { - authority_key_id->keyIdentifier.len = len; - authority_key_id->keyIdentifier.p = *p; - /* Setting tag of the keyIdentfier intentionally to 0x04. - * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL), - * its tag with the content is the payload of on OCTET STRING primitive */ - authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING; - - *p += len; - } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*p < end) { - /* Getting authorityCertIssuer using the required specific class tag [1] */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | - 1)) != 0) { - /* authorityCertIssuer and authorityCertSerialNumber MUST both - be present or both be absent. At this point we expect to have both. */ - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - /* "end" also includes the CertSerialNumber field so "len" shall be used */ - ret = mbedtls_x509_get_subject_alt_name_ext(p, - (*p+len), - &authority_key_id->authorityCertIssuer); - if (ret != 0) { - return ret; - } - - /* Getting authorityCertSerialNumber using the required specific class tag [2] */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - authority_key_id->authorityCertSerialNumber.len = len; - authority_key_id->authorityCertSerialNumber.p = *p; - authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER; - *p += len; - } - - if (*p != end) { - return MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - } - - return 0; -} - -/* - * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } - * - * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } - * - * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation - * - * PolicyInformation ::= SEQUENCE { - * policyIdentifier CertPolicyId, - * policyQualifiers SEQUENCE SIZE (1..MAX) OF - * PolicyQualifierInfo OPTIONAL } - * - * CertPolicyId ::= OBJECT IDENTIFIER - * - * PolicyQualifierInfo ::= SEQUENCE { - * policyQualifierId PolicyQualifierId, - * qualifier ANY DEFINED BY policyQualifierId } - * - * -- policyQualifierIds for Internet policy qualifiers - * - * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } - * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } - * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } - * - * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) - * - * Qualifier ::= CHOICE { - * cPSuri CPSuri, - * userNotice UserNotice } - * - * CPSuri ::= IA5String - * - * UserNotice ::= SEQUENCE { - * noticeRef NoticeReference OPTIONAL, - * explicitText DisplayText OPTIONAL } - * - * NoticeReference ::= SEQUENCE { - * organization DisplayText, - * noticeNumbers SEQUENCE OF INTEGER } - * - * DisplayText ::= CHOICE { - * ia5String IA5String (SIZE (1..200)), - * visibleString VisibleString (SIZE (1..200)), - * bmpString BMPString (SIZE (1..200)), - * utf8String UTF8String (SIZE (1..200)) } - * - * NOTE: we only parse and use anyPolicy without qualifiers at this point - * as defined in RFC 5280. - */ -static int x509_get_certificate_policies(unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *certificate_policies) -{ - int ret, parse_ret = 0; - size_t len; - mbedtls_asn1_buf *buf; - mbedtls_asn1_sequence *cur = certificate_policies; - - /* Get main sequence tag */ - ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); - if (ret != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - if (*p + len != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* - * Cannot be an empty sequence. - */ - if (len == 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - while (*p < end) { - mbedtls_x509_buf policy_oid; - const unsigned char *policy_end; - - /* - * Get the policy sequence - */ - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - policy_end = *p + len; - - if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, - MBEDTLS_ASN1_OID)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - policy_oid.tag = MBEDTLS_ASN1_OID; - policy_oid.len = len; - policy_oid.p = *p; - - /* - * Only AnyPolicy is currently supported when enforcing policy. - */ - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_POLICY, &policy_oid) != 0) { - /* - * Set the parsing return code but continue parsing, in case this - * extension is critical. - */ - parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } - - /* Allocate and assign next pointer */ - if (cur->buf.p != NULL) { - if (cur->next != NULL) { - return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; - } - - cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); - - if (cur->next == NULL) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_ALLOC_FAILED); - } - - cur = cur->next; - } - - buf = &(cur->buf); - buf->tag = policy_oid.tag; - buf->p = policy_oid.p; - buf->len = policy_oid.len; - - *p += len; - - /* - * If there is an optional qualifier, then *p < policy_end - * Check the Qualifier len to verify it doesn't exceed policy_end. - */ - if (*p < policy_end) { - if ((ret = mbedtls_asn1_get_tag(p, policy_end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != - 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - /* - * Skip the optional policy qualifiers. - */ - *p += len; - } - - if (*p != policy_end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return parse_ret; -} - -/* - * X.509 v3 extensions - * - */ -static int x509_get_crt_ext(unsigned char **p, - const unsigned char *end, - mbedtls_x509_crt *crt, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; - - if (*p == end) { - return 0; - } - - if ((ret = mbedtls_x509_get_ext(p, end, &crt->v3_ext, 3)) != 0) { - return ret; - } - - end = crt->v3_ext.p + crt->v3_ext.len; - while (*p < end) { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - mbedtls_x509_buf extn_oid = { 0, 0, NULL }; - int is_critical = 0; /* DEFAULT FALSE */ - int ext_type = 0; - - if ((ret = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - end_ext_data = *p + len; - - /* Get extension ID */ - if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len, - MBEDTLS_ASN1_OID)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - extn_oid.tag = MBEDTLS_ASN1_OID; - extn_oid.p = *p; - *p += extn_oid.len; - - /* Get optional critical */ - if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 && - (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - /* Data should be octet string type */ - if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len, - MBEDTLS_ASN1_OCTET_STRING)) != 0) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); - } - - start_ext_octet = *p; - end_ext_octet = *p + len; - - if (end_ext_octet != end_ext_data) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - /* - * Detect supported extensions - */ - ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type); - - if (ret != 0) { - /* Give the callback (if any) a chance to handle the extension */ - if (cb != NULL) { - ret = cb(p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet); - if (ret != 0 && is_critical) { - return ret; - } - *p = end_ext_octet; - continue; - } - - /* No parser found, skip extension */ - *p = end_ext_octet; - - if (is_critical) { - /* Data is marked as critical: fail */ - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); - } - continue; - } - - /* Forbid repeated extensions */ - if ((crt->ext_types & ext_type) != 0) { - return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; - } - - crt->ext_types |= ext_type; - - switch (ext_type) { - case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: - /* Parse basic constraints */ - if ((ret = x509_get_basic_constraints(p, end_ext_octet, - &crt->ca_istrue, &crt->max_pathlen)) != 0) { - return ret; - } - break; - - case MBEDTLS_X509_EXT_KEY_USAGE: - /* Parse key usage */ - if ((ret = mbedtls_x509_get_key_usage(p, end_ext_octet, - &crt->key_usage)) != 0) { - return ret; - } - break; - - case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: - /* Parse extended key usage */ - if ((ret = x509_get_ext_key_usage(p, end_ext_octet, - &crt->ext_key_usage)) != 0) { - return ret; - } - break; - - case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER: - /* Parse subject key identifier */ - if ((ret = x509_get_subject_key_id(p, end_ext_data, - &crt->subject_key_id)) != 0) { - return ret; - } - break; - - case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER: - /* Parse authority key identifier */ - if ((ret = x509_get_authority_key_id(p, end_ext_octet, - &crt->authority_key_id)) != 0) { - return ret; - } - break; - case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: - /* Parse subject alt name - * SubjectAltName ::= GeneralNames - */ - if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet, - &crt->subject_alt_names)) != 0) { - return ret; - } - break; - - case MBEDTLS_X509_EXT_NS_CERT_TYPE: - /* Parse netscape certificate type */ - if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_octet, - &crt->ns_cert_type)) != 0) { - return ret; - } - break; - - case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: - /* Parse certificate policies type */ - if ((ret = x509_get_certificate_policies(p, end_ext_octet, - &crt->certificate_policies)) != 0) { - /* Give the callback (if any) a chance to handle the extension - * if it contains unsupported policies */ - if (ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && - cb(p_ctx, crt, &extn_oid, is_critical, - start_ext_octet, end_ext_octet) == 0) { - break; - } - - if (is_critical) { - return ret; - } else - /* - * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we - * cannot interpret or enforce the policy. However, it is up to - * the user to choose how to enforce the policies, - * unless the extension is critical. - */ - if (ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { - return ret; - } - } - break; - - default: - /* - * If this is a non-critical extension, which the oid layer - * supports, but there isn't an x509 parser for it, - * skip the extension. - */ - if (is_critical) { - return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; - } else { - *p = end_ext_octet; - } - } - } - - if (*p != end) { - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * Parse and fill a single X.509 certificate in DER format - */ -static int x509_crt_parse_der_core(mbedtls_x509_crt *crt, - const unsigned char *buf, - size_t buflen, - int make_copy, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t len; - unsigned char *p, *end, *crt_end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - - memset(&sig_params1, 0, sizeof(mbedtls_x509_buf)); - memset(&sig_params2, 0, sizeof(mbedtls_x509_buf)); - memset(&sig_oid2, 0, sizeof(mbedtls_x509_buf)); - - /* - * Check for valid input - */ - if (crt == NULL || buf == NULL) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - /* Use the original buffer until we figure out actual length. */ - p = (unsigned char *) buf; - len = buflen; - end = p + len; - - /* - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERR_X509_INVALID_FORMAT; - } - - end = crt_end = p + len; - crt->raw.len = crt_end - buf; - if (make_copy != 0) { - /* Create and populate a new buffer for the raw field. */ - crt->raw.p = p = mbedtls_calloc(1, crt->raw.len); - if (crt->raw.p == NULL) { - return MBEDTLS_ERR_X509_ALLOC_FAILED; - } - - memcpy(crt->raw.p, buf, crt->raw.len); - crt->own_buffer = 1; - - p += crt->raw.len - len; - end = crt_end = p + len; - } else { - crt->raw.p = (unsigned char *) buf; - crt->own_buffer = 0; - } - - /* - * TBSCertificate ::= SEQUENCE { - */ - crt->tbs.p = p; - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); - } - - end = p + len; - crt->tbs.len = end - crt->tbs.p; - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * signature AlgorithmIdentifier - */ - if ((ret = x509_get_version(&p, end, &crt->version)) != 0 || - (ret = mbedtls_x509_get_serial(&p, end, &crt->serial)) != 0 || - (ret = mbedtls_x509_get_alg(&p, end, &crt->sig_oid, - &sig_params1)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - if (crt->version < 0 || crt->version > 2) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERR_X509_UNKNOWN_VERSION; - } - - crt->version++; - - if ((ret = mbedtls_x509_get_sig_alg(&crt->sig_oid, &sig_params1, - &crt->sig_md, &crt->sig_pk, - &crt->sig_opts)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - /* - * issuer Name - */ - crt->issuer_raw.p = p; - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); - } - - if ((ret = mbedtls_x509_get_name(&p, p + len, &crt->issuer)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - crt->issuer_raw.len = p - crt->issuer_raw.p; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - * - */ - if ((ret = x509_get_dates(&p, end, &crt->valid_from, - &crt->valid_to)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - /* - * subject Name - */ - crt->subject_raw.p = p; - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret); - } - - if (len && (ret = mbedtls_x509_get_name(&p, p + len, &crt->subject)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - crt->subject_raw.len = p - crt->subject_raw.p; - - /* - * SubjectPublicKeyInfo - */ - crt->pk_raw.p = p; - if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &crt->pk)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - crt->pk_raw.len = p - crt->pk_raw.p; - - /* - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - */ - if (crt->version == 2 || crt->version == 3) { - ret = x509_get_uid(&p, end, &crt->issuer_id, 1); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - } - - if (crt->version == 2 || crt->version == 3) { - ret = x509_get_uid(&p, end, &crt->subject_id, 2); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - } - - if (crt->version == 3) { - ret = x509_get_crt_ext(&p, end, crt, cb, p_ctx); - if (ret != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - } - - if (p != end) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - end = crt_end; - - /* - * } - * -- end of TBSCertificate - * - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if ((ret = mbedtls_x509_get_alg(&p, end, &sig_oid2, &sig_params2)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - if (crt->sig_oid.len != sig_oid2.len || - memcmp(crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len) != 0 || - sig_params1.tag != sig_params2.tag || - sig_params1.len != sig_params2.len || - (sig_params1.len != 0 && - memcmp(sig_params1.p, sig_params2.p, sig_params1.len) != 0)) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERR_X509_SIG_MISMATCH; - } - - if ((ret = mbedtls_x509_get_sig(&p, end, &crt->sig)) != 0) { - mbedtls_x509_crt_free(crt); - return ret; - } - - if (p != end) { - mbedtls_x509_crt_free(crt); - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); - } - - return 0; -} - -/* - * Parse one X.509 certificate in DER format from a buffer and add them to a - * chained list - */ -static int mbedtls_x509_crt_parse_der_internal(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen, - int make_copy, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *crt = chain, *prev = NULL; - - /* - * Check for valid input - */ - if (crt == NULL || buf == NULL) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - while (crt->version != 0 && crt->next != NULL) { - prev = crt; - crt = crt->next; - } - - /* - * Add new certificate on the end of the chain if needed. - */ - if (crt->version != 0 && crt->next == NULL) { - crt->next = mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); - - if (crt->next == NULL) { - return MBEDTLS_ERR_X509_ALLOC_FAILED; - } - - prev = crt; - mbedtls_x509_crt_init(crt->next); - crt = crt->next; - } - - ret = x509_crt_parse_der_core(crt, buf, buflen, make_copy, cb, p_ctx); - if (ret != 0) { - if (prev) { - prev->next = NULL; - } - - if (crt != chain) { - mbedtls_free(crt); - } - - return ret; - } - - return 0; -} - -int mbedtls_x509_crt_parse_der_nocopy(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen) -{ - return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 0, NULL, NULL); -} - -int mbedtls_x509_crt_parse_der_with_ext_cb(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen, - int make_copy, - mbedtls_x509_crt_ext_cb_t cb, - void *p_ctx) -{ - return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, make_copy, cb, p_ctx); -} - -int mbedtls_x509_crt_parse_der(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen) -{ - return mbedtls_x509_crt_parse_der_internal(chain, buf, buflen, 1, NULL, NULL); -} - -/* - * Parse one or more PEM certificates from a buffer and add them to the chained - * list - */ -int mbedtls_x509_crt_parse(mbedtls_x509_crt *chain, - const unsigned char *buf, - size_t buflen) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int success = 0, first_error = 0, total_failed = 0; - int buf_format = MBEDTLS_X509_FORMAT_DER; -#endif - - /* - * Check for valid input - */ - if (chain == NULL || buf == NULL) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - /* - * Determine buffer content. Buffer contains either one DER certificate or - * one or more PEM certificates. - */ -#if defined(MBEDTLS_PEM_PARSE_C) - if (buflen != 0 && buf[buflen - 1] == '\0' && - strstr((const char *) buf, "-----BEGIN CERTIFICATE-----") != NULL) { - buf_format = MBEDTLS_X509_FORMAT_PEM; - } - - if (buf_format == MBEDTLS_X509_FORMAT_DER) { - return mbedtls_x509_crt_parse_der(chain, buf, buflen); - } -#else - return mbedtls_x509_crt_parse_der(chain, buf, buflen); -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) - if (buf_format == MBEDTLS_X509_FORMAT_PEM) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_pem_context pem; - - /* 1 rather than 0 since the terminating NULL byte is counted in */ - while (buflen > 1) { - size_t use_len; - mbedtls_pem_init(&pem); - - /* If we get there, we know the string is null-terminated */ - ret = mbedtls_pem_read_buffer(&pem, - "-----BEGIN CERTIFICATE-----", - "-----END CERTIFICATE-----", - buf, NULL, 0, &use_len); - - if (ret == 0) { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - } else if (ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA) { - return ret; - } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) { - mbedtls_pem_free(&pem); - - /* - * PEM header and footer were found - */ - buflen -= use_len; - buf += use_len; - - if (first_error == 0) { - first_error = ret; - } - - total_failed++; - continue; - } else { - break; - } - - ret = mbedtls_x509_crt_parse_der(chain, pem.buf, pem.buflen); - - mbedtls_pem_free(&pem); - - if (ret != 0) { - /* - * Quit parsing on a memory error - */ - if (ret == MBEDTLS_ERR_X509_ALLOC_FAILED) { - return ret; - } - - if (first_error == 0) { - first_error = ret; - } - - total_failed++; - continue; - } - - success = 1; - } - } - - if (success) { - return total_failed; - } else if (first_error) { - return first_error; - } else { - return MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT; - } -#endif /* MBEDTLS_PEM_PARSE_C */ -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more certificates and add them to the chained list - */ -int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - unsigned char *buf; - - if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) { - return ret; - } - - ret = mbedtls_x509_crt_parse(chain, buf, n); - - mbedtls_zeroize_and_free(buf, n); - - return ret; -} - -#if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) -int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path) -{ - int ret = 0; -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - int w_ret; - WCHAR szDir[MAX_PATH]; - char filename[MAX_PATH]; - char *p; - size_t len = strlen(path); - - WIN32_FIND_DATAW file_data; - HANDLE hFind; - - if (len > MAX_PATH - 3) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - memset(szDir, 0, sizeof(szDir)); - memset(filename, 0, MAX_PATH); - memcpy(filename, path, len); - filename[len++] = '\\'; - p = filename + len; - filename[len++] = '*'; - - /* - * Note this function uses the code page CP_ACP which is the system default - * ANSI codepage. The input string is always described in BYTES and the - * output length is described in WCHARs. - */ - w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir, - MAX_PATH - 3); - if (w_ret == 0) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - hFind = FindFirstFileW(szDir, &file_data); - if (hFind == INVALID_HANDLE_VALUE) { - return MBEDTLS_ERR_X509_FILE_IO_ERROR; - } - - len = MAX_PATH - len; - do { - memset(p, 0, len); - - if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - continue; - } - w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName, - -1, p, (int) len, NULL, NULL); - if (w_ret == 0) { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - - w_ret = mbedtls_x509_crt_parse_file(chain, filename); - if (w_ret < 0) { - ret++; - } else { - ret += w_ret; - } - } while (FindNextFileW(hFind, &file_data) != 0); - - if (GetLastError() != ERROR_NO_MORE_FILES) { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - } - -cleanup: - FindClose(hFind); -#else /* _WIN32 */ - int t_ret; - int snp_ret; - struct stat sb; - struct dirent *entry; - char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; - DIR *dir = opendir(path); - - if (dir == NULL) { - return MBEDTLS_ERR_X509_FILE_IO_ERROR; - } - -#if defined(MBEDTLS_THREADING_C) - if ((ret = mbedtls_mutex_lock(&mbedtls_threading_readdir_mutex)) != 0) { - closedir(dir); - return ret; - } -#endif /* MBEDTLS_THREADING_C */ - - memset(&sb, 0, sizeof(sb)); - - while ((entry = readdir(dir)) != NULL) { - snp_ret = mbedtls_snprintf(entry_name, sizeof(entry_name), - "%s/%s", path, entry->d_name); - - if (snp_ret < 0 || (size_t) snp_ret >= sizeof(entry_name)) { - ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - goto cleanup; - } else if (stat(entry_name, &sb) == -1) { - if (errno == ENOENT) { - /* Broken symbolic link - ignore this entry. - stat(2) will return this error for either (a) a dangling - symlink or (b) a missing file. - Given that we have just obtained the filename from readdir, - assume that it does exist and therefore treat this as a - dangling symlink. */ - continue; - } else { - /* Some other file error; report the error. */ - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - } - - if (!S_ISREG(sb.st_mode)) { - continue; - } - - // Ignore parse errors - // - t_ret = mbedtls_x509_crt_parse_file(chain, entry_name); - if (t_ret < 0) { - ret++; - } else { - ret += t_ret; - } - } - -cleanup: - closedir(dir); - -#if defined(MBEDTLS_THREADING_C) - if (mbedtls_mutex_unlock(&mbedtls_threading_readdir_mutex) != 0) { - ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; - } -#endif /* MBEDTLS_THREADING_C */ - -#endif /* _WIN32 */ - - return ret; -} -#endif /* #if !defined( MBEDTLS_X509_CRT_PARSE_PATH_ALT ) */ -#endif /* MBEDTLS_FS_IO */ - -#if !defined(MBEDTLS_X509_REMOVE_INFO) -#define PRINT_ITEM(i) \ - do { \ - ret = mbedtls_snprintf(p, n, "%s" i, sep); \ - MBEDTLS_X509_SAFE_SNPRINTF; \ - sep = ", "; \ - } while (0) - -#define CERT_TYPE(type, name) \ - do { \ - if (ns_cert_type & (type)) { \ - PRINT_ITEM(name); \ - } \ - } while (0) - -#define KEY_USAGE(code, name) \ - do { \ - if (key_usage & (code)) { \ - PRINT_ITEM(name); \ - } \ - } while (0) - -static int x509_info_ext_key_usage(char **buf, size_t *size, - const mbedtls_x509_sequence *extended_key_usage) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = extended_key_usage; - const char *sep = ""; - - while (cur != NULL) { - if (mbedtls_oid_get_extended_key_usage(&cur->buf, &desc) != 0) { - desc = "???"; - } - - ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return 0; -} - -static int x509_info_cert_policies(char **buf, size_t *size, - const mbedtls_x509_sequence *certificate_policies) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = certificate_policies; - const char *sep = ""; - - while (cur != NULL) { - if (mbedtls_oid_get_certificate_policies(&cur->buf, &desc) != 0) { - desc = "???"; - } - - ret = mbedtls_snprintf(p, n, "%s%s", sep, desc); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return 0; -} - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 18 -#define BC "18" -int mbedtls_x509_crt_info(char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - if (NULL == crt) { - ret = mbedtls_snprintf(p, n, "\nCertificate is uninitialised!\n"); - MBEDTLS_X509_SAFE_SNPRINTF; - - return (int) (size - n); - } - - ret = mbedtls_snprintf(p, n, "%scert. version : %d\n", - prefix, crt->version); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_snprintf(p, n, "%sserial number : ", - prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets(p, n, &crt->serial); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%sissuer name : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets(p, n, &crt->issuer); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets(p, n, &crt->subject); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%sissued on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_from.year, crt->valid_from.mon, - crt->valid_from.day, crt->valid_from.hour, - crt->valid_from.min, crt->valid_from.sec); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%sexpires on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_to.year, crt->valid_to.mon, - crt->valid_to.day, crt->valid_to.hour, - crt->valid_to.min, crt->valid_to.sec); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets(p, n, &crt->sig_oid, crt->sig_pk, - crt->sig_md, crt->sig_opts); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* Key size */ - if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON, - mbedtls_pk_get_name(&crt->pk))) != 0) { - return ret; - } - - ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, - (int) mbedtls_pk_get_bitlen(&crt->pk)); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* - * Optional extensions - */ - - if (crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) { - ret = mbedtls_snprintf(p, n, "\n%sbasic constraints : CA=%s", prefix, - crt->ca_istrue ? "true" : "false"); - MBEDTLS_X509_SAFE_SNPRINTF; - - if (crt->max_pathlen > 0) { - ret = mbedtls_snprintf(p, n, ", max_pathlen=%d", crt->max_pathlen - 1); - MBEDTLS_X509_SAFE_SNPRINTF; - } - } - - if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { - ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n, - &crt->subject_alt_names, - prefix)) != 0) { - return ret; - } - } - - if (crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) { - ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = mbedtls_x509_info_cert_type(&p, &n, crt->ns_cert_type)) != 0) { - return ret; - } - } - - if (crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) { - ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = mbedtls_x509_info_key_usage(&p, &n, crt->key_usage)) != 0) { - return ret; - } - } - - if (crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) { - ret = mbedtls_snprintf(p, n, "\n%sext key usage : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_ext_key_usage(&p, &n, - &crt->ext_key_usage)) != 0) { - return ret; - } - } - - if (crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES) { - ret = mbedtls_snprintf(p, n, "\n%scertificate policies : ", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - - if ((ret = x509_info_cert_policies(&p, &n, - &crt->certificate_policies)) != 0) { - return ret; - } - } - - ret = mbedtls_snprintf(p, n, "\n"); - MBEDTLS_X509_SAFE_SNPRINTF; - - return (int) (size - n); -} - -struct x509_crt_verify_string { - int code; - const char *string; -}; - -#define X509_CRT_ERROR_INFO(err, err_str, info) { err, info }, -static const struct x509_crt_verify_string x509_crt_verify_strings[] = { - MBEDTLS_X509_CRT_ERROR_INFO_LIST - { 0, NULL } -}; -#undef X509_CRT_ERROR_INFO - -int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix, - uint32_t flags) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const struct x509_crt_verify_string *cur; - char *p = buf; - size_t n = size; - - for (cur = x509_crt_verify_strings; cur->string != NULL; cur++) { - if ((flags & cur->code) == 0) { - continue; - } - - ret = mbedtls_snprintf(p, n, "%s%s\n", prefix, cur->string); - MBEDTLS_X509_SAFE_SNPRINTF; - flags ^= cur->code; - } - - if (flags != 0) { - ret = mbedtls_snprintf(p, n, "%sUnknown reason " - "(this should not happen)\n", prefix); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return (int) (size - n); -} -#endif /* MBEDTLS_X509_REMOVE_INFO */ - -int mbedtls_x509_crt_check_key_usage(const mbedtls_x509_crt *crt, - unsigned int usage) -{ - unsigned int usage_must, usage_may; - unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY - | MBEDTLS_X509_KU_DECIPHER_ONLY; - - if ((crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) == 0) { - return 0; - } - - usage_must = usage & ~may_mask; - - if (((crt->key_usage & ~may_mask) & usage_must) != usage_must) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - usage_may = usage & may_mask; - - if (((crt->key_usage & may_mask) | usage_may) != usage_may) { - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; - } - - return 0; -} - -int mbedtls_x509_crt_check_extended_key_usage(const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len) -{ - const mbedtls_x509_sequence *cur; - - /* Extension is not mandatory, absent means no restriction */ - if ((crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE) == 0) { - return 0; - } - - /* - * Look for the requested usage (or wildcard ANY) in our list - */ - for (cur = &crt->ext_key_usage; cur != NULL; cur = cur->next) { - const mbedtls_x509_buf *cur_oid = &cur->buf; - - if (cur_oid->len == usage_len && - memcmp(cur_oid->p, usage_oid, usage_len) == 0) { - return 0; - } - - if (MBEDTLS_OID_CMP(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid) == 0) { - return 0; - } - } - - return MBEDTLS_ERR_X509_BAD_INPUT_DATA; -} - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/* - * Return 1 if the certificate is revoked, or 0 otherwise. - */ -int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl) -{ - const mbedtls_x509_crl_entry *cur = &crl->entry; - - while (cur != NULL && cur->serial.len != 0) { - if (crt->serial.len == cur->serial.len && - memcmp(crt->serial.p, cur->serial.p, crt->serial.len) == 0) { - return 1; - } - - cur = cur->next; - } - - return 0; -} - -/* - * Check that the given certificate is not revoked according to the CRL. - * Skip validation if no CRL for the given CA is present. - */ -static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, - mbedtls_x509_crl *crl_list, - const mbedtls_x509_crt_profile *profile, - const mbedtls_x509_time *now) -{ - int flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_algorithm_t psa_algorithm; -#else - const mbedtls_md_info_t *md_info; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - size_t hash_length; - - if (ca == NULL) { - return flags; - } - - while (crl_list != NULL) { - if (crl_list->version == 0 || - x509_name_cmp(&crl_list->issuer, &ca->subject) != 0) { - crl_list = crl_list->next; - continue; - } - - /* - * Check if the CA is configured to sign CRLs - */ - if (mbedtls_x509_crt_check_key_usage(ca, - MBEDTLS_X509_KU_CRL_SIGN) != 0) { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - /* - * Check if CRL is correctly signed by the trusted CA - */ - if (x509_profile_check_md_alg(profile, crl_list->sig_md) != 0) { - flags |= MBEDTLS_X509_BADCRL_BAD_MD; - } - - if (x509_profile_check_pk_alg(profile, crl_list->sig_pk) != 0) { - flags |= MBEDTLS_X509_BADCRL_BAD_PK; - } - -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md); - if (psa_hash_compute(psa_algorithm, - crl_list->tbs.p, - crl_list->tbs.len, - hash, - sizeof(hash), - &hash_length) != PSA_SUCCESS) { - /* Note: this can't happen except after an internal error */ - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } -#else - md_info = mbedtls_md_info_from_type(crl_list->sig_md); - hash_length = mbedtls_md_get_size(md_info); - if (mbedtls_md(md_info, - crl_list->tbs.p, - crl_list->tbs.len, - hash) != 0) { - /* Note: this can't happen except after an internal error */ - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - if (x509_profile_check_key(profile, &ca->pk) != 0) { - flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } - - if (mbedtls_pk_verify_ext(crl_list->sig_pk, crl_list->sig_opts, &ca->pk, - crl_list->sig_md, hash, hash_length, - crl_list->sig.p, crl_list->sig.len) != 0) { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - -#if defined(MBEDTLS_HAVE_TIME_DATE) - /* - * Check for validity of CRL (Do not drop out) - */ - if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) { - flags |= MBEDTLS_X509_BADCRL_EXPIRED; - } - - if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) { - flags |= MBEDTLS_X509_BADCRL_FUTURE; - } -#else - ((void) now); -#endif - - /* - * Check if certificate is revoked - */ - if (mbedtls_x509_crt_is_revoked(crt, crl_list)) { - flags |= MBEDTLS_X509_BADCERT_REVOKED; - break; - } - - crl_list = crl_list->next; - } - - return flags; -} -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/* - * Check the signature of a certificate by its parent - */ -static int x509_crt_check_signature(const mbedtls_x509_crt *child, - mbedtls_x509_crt *parent, - mbedtls_x509_crt_restart_ctx *rs_ctx) -{ - size_t hash_len; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; -#if !defined(MBEDTLS_USE_PSA_CRYPTO) - const mbedtls_md_info_t *md_info; - md_info = mbedtls_md_info_from_type(child->sig_md); - hash_len = mbedtls_md_get_size(md_info); - - /* Note: hash errors can happen only after an internal error */ - if (mbedtls_md(md_info, child->tbs.p, child->tbs.len, hash) != 0) { - return -1; - } -#else - psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md); - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - status = psa_hash_compute(hash_alg, - child->tbs.p, - child->tbs.len, - hash, - sizeof(hash), - &hash_len); - if (status != PSA_SUCCESS) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - /* Skip expensive computation on obvious mismatch */ - if (!mbedtls_pk_can_do(&parent->pk, child->sig_pk)) { - return -1; - } - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA) { - return mbedtls_pk_verify_restartable(&parent->pk, - child->sig_md, hash, hash_len, - child->sig.p, child->sig.len, &rs_ctx->pk); - } -#else - (void) rs_ctx; -#endif - - return mbedtls_pk_verify_ext(child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, hash_len, - child->sig.p, child->sig.len); -} - -/* - * Check if 'parent' is a suitable parent (signing CA) for 'child'. - * Return 0 if yes, -1 if not. - * - * top means parent is a locally-trusted certificate - */ -static int x509_crt_check_parent(const mbedtls_x509_crt *child, - const mbedtls_x509_crt *parent, - int top) -{ - int need_ca_bit; - - /* Parent must be the issuer */ - if (x509_name_cmp(&child->issuer, &parent->subject) != 0) { - return -1; - } - - /* Parent must have the basicConstraints CA bit set as a general rule */ - need_ca_bit = 1; - - /* Exception: v1/v2 certificates that are locally trusted. */ - if (top && parent->version < 3) { - need_ca_bit = 0; - } - - if (need_ca_bit && !parent->ca_istrue) { - return -1; - } - - if (need_ca_bit && - mbedtls_x509_crt_check_key_usage(parent, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0) { - return -1; - } - - return 0; -} - -/* - * Find a suitable parent for child in candidates, or return NULL. - * - * Here suitable is defined as: - * 1. subject name matches child's issuer - * 2. if necessary, the CA bit is set and key usage allows signing certs - * 3. for trusted roots, the signature is correct - * (for intermediates, the signature is checked and the result reported) - * 4. pathlen constraints are satisfied - * - * If there's a suitable candidate which is also time-valid, return the first - * such. Otherwise, return the first suitable candidate (or NULL if there is - * none). - * - * The rationale for this rule is that someone could have a list of trusted - * roots with two versions on the same root with different validity periods. - * (At least one user reported having such a list and wanted it to just work.) - * The reason we don't just require time-validity is that generally there is - * only one version, and if it's expired we want the flags to state that - * rather than NOT_TRUSTED, as would be the case if we required it here. - * - * The rationale for rule 3 (signature for trusted roots) is that users might - * have two versions of the same CA with different keys in their list, and the - * way we select the correct one is by checking the signature (as we don't - * rely on key identifier extensions). (This is one way users might choose to - * handle key rollover, another relies on self-issued certs, see [SIRO].) - * - * Arguments: - * - [in] child: certificate for which we're looking for a parent - * - [in] candidates: chained list of potential parents - * - [out] r_parent: parent found (or NULL) - * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 - * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top - * of the chain, 0 otherwise - * - [in] path_cnt: number of intermediates seen so far - * - [in] self_cnt: number of self-signed intermediates seen so far - * (will never be greater than path_cnt) - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - 0 on success - * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise - */ -static int x509_crt_find_parent_in( - mbedtls_x509_crt *child, - mbedtls_x509_crt *candidates, - mbedtls_x509_crt **r_parent, - int *r_signature_is_good, - int top, - unsigned path_cnt, - unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx, - const mbedtls_x509_time *now) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *parent, *fallback_parent; - int signature_is_good = 0, fallback_signature_is_good; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* did we have something in progress? */ - if (rs_ctx != NULL && rs_ctx->parent != NULL) { - /* restore saved state */ - parent = rs_ctx->parent; - fallback_parent = rs_ctx->fallback_parent; - fallback_signature_is_good = rs_ctx->fallback_signature_is_good; - - /* clear saved state */ - rs_ctx->parent = NULL; - rs_ctx->fallback_parent = NULL; - rs_ctx->fallback_signature_is_good = 0; - - /* resume where we left */ - goto check_signature; - } -#endif - - fallback_parent = NULL; - fallback_signature_is_good = 0; - - for (parent = candidates; parent != NULL; parent = parent->next) { - /* basic parenting skills (name, CA bit, key usage) */ - if (x509_crt_check_parent(child, parent, top) != 0) { - continue; - } - - /* +1 because stored max_pathlen is 1 higher that the actual value */ - if (parent->max_pathlen > 0 && - (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt) { - continue; - } - - /* Signature */ -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -check_signature: -#endif - ret = x509_crt_check_signature(child, parent, rs_ctx); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->parent = parent; - rs_ctx->fallback_parent = fallback_parent; - rs_ctx->fallback_signature_is_good = fallback_signature_is_good; - - return ret; - } -#else - (void) ret; -#endif - - signature_is_good = ret == 0; - if (top && !signature_is_good) { - continue; - } - -#if defined(MBEDTLS_HAVE_TIME_DATE) - /* optional time check */ - if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 || /* past */ - mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) { /* future */ - if (fallback_parent == NULL) { - fallback_parent = parent; - fallback_signature_is_good = signature_is_good; - } - - continue; - } -#else - ((void) now); -#endif - - *r_parent = parent; - *r_signature_is_good = signature_is_good; - - break; - } - - if (parent == NULL) { - *r_parent = fallback_parent; - *r_signature_is_good = fallback_signature_is_good; - } - - return 0; -} - -/* - * Find a parent in trusted CAs or the provided chain, or return NULL. - * - * Searches in trusted CAs first, and return the first suitable parent found - * (see find_parent_in() for definition of suitable). - * - * Arguments: - * - [in] child: certificate for which we're looking for a parent, followed - * by a chain of possible intermediates - * - [in] trust_ca: list of locally trusted certificates - * - [out] parent: parent found (or NULL) - * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 - * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 - * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) - * - [in] self_cnt: number of self-signed certs in the chain so far - * (will always be no greater than path_cnt) - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - 0 on success - * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise - */ -static int x509_crt_find_parent( - mbedtls_x509_crt *child, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crt **parent, - int *parent_is_trusted, - int *signature_is_good, - unsigned path_cnt, - unsigned self_cnt, - mbedtls_x509_crt_restart_ctx *rs_ctx, - const mbedtls_x509_time *now) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_x509_crt *search_list; - - *parent_is_trusted = 1; - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* restore then clear saved state if we have some stored */ - if (rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) { - *parent_is_trusted = rs_ctx->parent_is_trusted; - rs_ctx->parent_is_trusted = -1; - } -#endif - - while (1) { - search_list = *parent_is_trusted ? trust_ca : child->next; - - ret = x509_crt_find_parent_in(child, search_list, - parent, signature_is_good, - *parent_is_trusted, - path_cnt, self_cnt, rs_ctx, now); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->parent_is_trusted = *parent_is_trusted; - return ret; - } -#else - (void) ret; -#endif - - /* stop here if found or already in second iteration */ - if (*parent != NULL || *parent_is_trusted == 0) { - break; - } - - /* prepare second iteration */ - *parent_is_trusted = 0; - } - - /* extra precaution against mistakes in the caller */ - if (*parent == NULL) { - *parent_is_trusted = 0; - *signature_is_good = 0; - } - - return 0; -} - -/* - * Check if an end-entity certificate is locally trusted - * - * Currently we require such certificates to be self-signed (actually only - * check for self-issued as self-signatures are not checked) - */ -static int x509_crt_check_ee_locally_trusted( - mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca) -{ - mbedtls_x509_crt *cur; - - /* must be self-issued */ - if (x509_name_cmp(&crt->issuer, &crt->subject) != 0) { - return -1; - } - - /* look for an exact match with trusted cert */ - for (cur = trust_ca; cur != NULL; cur = cur->next) { - if (crt->raw.len == cur->raw.len && - memcmp(crt->raw.p, cur->raw.p, crt->raw.len) == 0) { - return 0; - } - } - - /* too bad */ - return -1; -} - -/* - * Build and verify a certificate chain - * - * Given a peer-provided list of certificates EE, C1, ..., Cn and - * a list of trusted certs R1, ... Rp, try to build and verify a chain - * EE, Ci1, ... Ciq [, Rj] - * such that every cert in the chain is a child of the next one, - * jumping to a trusted root as early as possible. - * - * Verify that chain and return it with flags for all issues found. - * - * Special cases: - * - EE == Rj -> return a one-element list containing it - * - EE, Ci1, ..., Ciq cannot be continued with a trusted root - * -> return that chain with NOT_TRUSTED set on Ciq - * - * Tests for (aspects of) this function should include at least: - * - trusted EE - * - EE -> trusted root - * - EE -> intermediate CA -> trusted root - * - if relevant: EE untrusted - * - if relevant: EE -> intermediate, untrusted - * with the aspect under test checked at each relevant level (EE, int, root). - * For some aspects longer chains are required, but usually length 2 is - * enough (but length 1 is not in general). - * - * Arguments: - * - [in] crt: the cert list EE, C1, ..., Cn - * - [in] trust_ca: the trusted list R1, ..., Rp - * - [in] ca_crl, profile: as in verify_with_profile() - * - [out] ver_chain: the built and verified chain - * Only valid when return value is 0, may contain garbage otherwise! - * Restart note: need not be the same when calling again to resume. - * - [in-out] rs_ctx: context for restarting operations - * - * Return value: - * - non-zero if the chain could not be fully built and examined - * - 0 is the chain was successfully built and examined, - * even if it was found to be invalid - */ -static int x509_crt_verify_chain( - mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - mbedtls_x509_crt_ca_cb_t f_ca_cb, - void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, - mbedtls_x509_crt_verify_chain *ver_chain, - mbedtls_x509_crt_restart_ctx *rs_ctx) -{ - /* Don't initialize any of those variables here, so that the compiler can - * catch potential issues with jumping ahead when restarting */ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - uint32_t *flags; - mbedtls_x509_crt_verify_chain_item *cur; - mbedtls_x509_crt *child; - mbedtls_x509_crt *parent; - int parent_is_trusted; - int child_is_trusted; - int signature_is_good; - unsigned self_cnt; - mbedtls_x509_crt *cur_trust_ca = NULL; - mbedtls_x509_time now; - -#if defined(MBEDTLS_HAVE_TIME_DATE) - if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) { - return MBEDTLS_ERR_X509_FATAL_ERROR; - } -#endif - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* resume if we had an operation in progress */ - if (rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent) { - /* restore saved state */ - *ver_chain = rs_ctx->ver_chain; /* struct copy */ - self_cnt = rs_ctx->self_cnt; - - /* restore derived state */ - cur = &ver_chain->items[ver_chain->len - 1]; - child = cur->crt; - flags = &cur->flags; - - goto find_parent; - } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - - child = crt; - self_cnt = 0; - parent_is_trusted = 0; - child_is_trusted = 0; - - while (1) { - /* Add certificate to the verification chain */ - cur = &ver_chain->items[ver_chain->len]; - cur->crt = child; - cur->flags = 0; - ver_chain->len++; - flags = &cur->flags; - -#if defined(MBEDTLS_HAVE_TIME_DATE) - /* Check time-validity (all certificates) */ - if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) { - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - } - - if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) { - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - } -#endif - - /* Stop here for trusted roots (but not for trusted EE certs) */ - if (child_is_trusted) { - return 0; - } - - /* Check signature algorithm: MD & PK algs */ - if (x509_profile_check_md_alg(profile, child->sig_md) != 0) { - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - } - - if (x509_profile_check_pk_alg(profile, child->sig_pk) != 0) { - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - } - - /* Special case: EE certs that are locally trusted */ - if (ver_chain->len == 1 && - x509_crt_check_ee_locally_trusted(child, trust_ca) == 0) { - return 0; - } - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -find_parent: -#endif - - /* Obtain list of potential trusted signers from CA callback, - * or use statically provided list. */ -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - if (f_ca_cb != NULL) { - mbedtls_x509_crt_free(ver_chain->trust_ca_cb_result); - mbedtls_free(ver_chain->trust_ca_cb_result); - ver_chain->trust_ca_cb_result = NULL; - - ret = f_ca_cb(p_ca_cb, child, &ver_chain->trust_ca_cb_result); - if (ret != 0) { - return MBEDTLS_ERR_X509_FATAL_ERROR; - } - - cur_trust_ca = ver_chain->trust_ca_cb_result; - } else -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - { - ((void) f_ca_cb); - ((void) p_ca_cb); - cur_trust_ca = trust_ca; - } - - /* Look for a parent in trusted CAs or up the chain */ - ret = x509_crt_find_parent(child, cur_trust_ca, &parent, - &parent_is_trusted, &signature_is_good, - ver_chain->len - 1, self_cnt, rs_ctx, - &now); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) { - /* save state */ - rs_ctx->in_progress = x509_crt_rs_find_parent; - rs_ctx->self_cnt = self_cnt; - rs_ctx->ver_chain = *ver_chain; /* struct copy */ - - return ret; - } -#else - (void) ret; -#endif - - /* No parent? We're done here */ - if (parent == NULL) { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - return 0; - } - - /* Count intermediate self-issued (not necessarily self-signed) certs. - * These can occur with some strategies for key rollover, see [SIRO], - * and should be excluded from max_pathlen checks. */ - if (ver_chain->len != 1 && - x509_name_cmp(&child->issuer, &child->subject) == 0) { - self_cnt++; - } - - /* path_cnt is 0 for the first intermediate CA, - * and if parent is trusted it's not an intermediate CA */ - if (!parent_is_trusted && - ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA) { - /* return immediately to avoid overflow the chain array */ - return MBEDTLS_ERR_X509_FATAL_ERROR; - } - - /* signature was checked while searching parent */ - if (!signature_is_good) { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - - /* check size of signing key */ - if (x509_profile_check_key(profile, &parent->pk) != 0) { - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now); -#else - (void) ca_crl; -#endif - - /* prepare for next iteration */ - child = parent; - parent = NULL; - child_is_trusted = parent_is_trusted; - signature_is_good = 0; - } -} - -#ifdef _WIN32 -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") -#include -#include -#elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600 -#include -#include -#else -/* inet_pton() is not supported, fallback to software version */ -#define MBEDTLS_TEST_SW_INET_PTON -#endif -#elif defined(__sun) -/* Solaris requires -lsocket -lnsl for inet_pton() */ -#elif defined(__has_include) -#if __has_include() -#include -#endif -#if __has_include() -#include -#endif -#endif - -/* Use whether or not AF_INET6 is defined to indicate whether or not to use - * the platform inet_pton() or a local implementation (below). The local - * implementation may be used even in cases where the platform provides - * inet_pton(), e.g. when there are different includes required and/or the - * platform implementation requires dependencies on additional libraries. - * Specifically, Windows requires custom includes and additional link - * dependencies, and Solaris requires additional link dependencies. - * Also, as a coarse heuristic, use the local implementation if the compiler - * does not support __has_include(), or if the definition of AF_INET6 is not - * provided by headers included (or not) via __has_include() above. - * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names - * despite having a platform that has inet_pton. */ -#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names -/* Definition located further below to possibly reduce compiler inlining */ -static int x509_inet_pton_ipv4(const char *src, void *dst); - -#define li_cton(c, n) \ - (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0)) - -static int x509_inet_pton_ipv6(const char *src, void *dst) -{ - const unsigned char *p = (const unsigned char *) src; - int nonzero_groups = 0, num_digits, zero_group_start = -1; - uint16_t addr[8]; - do { - /* note: allows excess leading 0's, e.g. 1:0002:3:... */ - uint16_t group = num_digits = 0; - for (uint8_t digit; num_digits < 4; num_digits++) { - if (li_cton(*p, digit) == 0) { - break; - } - group = (group << 4) | digit; - p++; - } - if (num_digits != 0) { - MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups); - nonzero_groups++; - if (*p == '\0') { - break; - } else if (*p == '.') { - /* Don't accept IPv4 too early or late */ - if ((nonzero_groups == 0 && zero_group_start == -1) || - nonzero_groups >= 7) { - break; - } - - /* Walk back to prior ':', then parse as IPv4-mapped */ - int steps = 4; - do { - p--; - steps--; - } while (*p != ':' && steps > 0); - - if (*p != ':') { - break; - } - p++; - nonzero_groups--; - if (x509_inet_pton_ipv4((const char *) p, - addr + nonzero_groups) != 0) { - break; - } - - nonzero_groups += 2; - p = (const unsigned char *) ""; - break; - } else if (*p != ':') { - return -1; - } - } else { - /* Don't accept a second zero group or an invalid delimiter */ - if (zero_group_start != -1 || *p != ':') { - return -1; - } - zero_group_start = nonzero_groups; - - /* Accept a zero group at start, but it has to be a double colon */ - if (zero_group_start == 0 && *++p != ':') { - return -1; - } - - if (p[1] == '\0') { - ++p; - break; - } - } - ++p; - } while (nonzero_groups < 8); - - if (*p != '\0') { - return -1; - } - - if (zero_group_start != -1) { - if (nonzero_groups > 6) { - return -1; - } - int zero_groups = 8 - nonzero_groups; - int groups_after_zero = nonzero_groups - zero_group_start; - - /* Move the non-zero part to after the zeroes */ - if (groups_after_zero) { - memmove(addr + zero_group_start + zero_groups, - addr + zero_group_start, - groups_after_zero * sizeof(*addr)); - } - memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr)); - } else { - if (nonzero_groups != 8) { - return -1; - } - } - memcpy(dst, addr, sizeof(addr)); - return 0; -} - -static int x509_inet_pton_ipv4(const char *src, void *dst) -{ - const unsigned char *p = (const unsigned char *) src; - uint8_t *res = (uint8_t *) dst; - uint8_t digit, num_digits = 0; - uint8_t num_octets = 0; - uint16_t octet; - - do { - octet = num_digits = 0; - do { - digit = *p - '0'; - if (digit > 9) { - break; - } - - /* Don't allow leading zeroes. These might mean octal format, - * which this implementation does not support. */ - if (octet == 0 && num_digits > 0) { - return -1; - } - - octet = octet * 10 + digit; - num_digits++; - p++; - } while (num_digits < 3); - - if (octet >= 256 || num_digits > 3 || num_digits == 0) { - return -1; - } - *res++ = (uint8_t) octet; - num_octets++; - } while (num_octets < 4 && *p++ == '.'); - return num_octets == 4 && *p == '\0' ? 0 : -1; -} - -#else - -static int x509_inet_pton_ipv6(const char *src, void *dst) -{ - return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1; -} - -static int x509_inet_pton_ipv4(const char *src, void *dst) -{ - return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1; -} - -#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names - -size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst) -{ - return strchr(cn, ':') == NULL - ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0 - : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0; -} - -/* - * Check for CN match - */ -static int x509_crt_check_cn(const mbedtls_x509_buf *name, - const char *cn, size_t cn_len) -{ - /* try exact match */ - if (name->len == cn_len && - x509_memcasecmp(cn, name->p, cn_len) == 0) { - return 0; - } - - /* try wildcard match */ - if (x509_check_wildcard(cn, name) == 0) { - return 0; - } - - return -1; -} - -static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san, - const char *cn, size_t cn_len) -{ - uint32_t ip[4]; - cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip); - if (cn_len == 0) { - return -1; - } - - for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { - const unsigned char san_type = (unsigned char) cur->buf.tag & - MBEDTLS_ASN1_TAG_VALUE_MASK; - if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS && - cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) { - return 0; - } - } - - return -1; -} - -static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san, - const char *cn, size_t cn_len) -{ - for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { - const unsigned char san_type = (unsigned char) cur->buf.tag & - MBEDTLS_ASN1_TAG_VALUE_MASK; - if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER && - cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) { - return 0; - } - } - - return -1; -} - -/* - * Check for SAN match, see RFC 5280 Section 4.2.1.6 - */ -static int x509_crt_check_san(const mbedtls_x509_sequence *san, - const char *cn, size_t cn_len) -{ - int san_ip = 0; - int san_uri = 0; - /* Prioritize DNS name over other subtypes due to popularity */ - for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) { - switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) { - case MBEDTLS_X509_SAN_DNS_NAME: - if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) { - return 0; - } - break; - case MBEDTLS_X509_SAN_IP_ADDRESS: - san_ip = 1; - break; - case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: - san_uri = 1; - break; - /* (We may handle other types here later.) */ - default: /* Unrecognized type */ - break; - } - } - if (san_ip) { - if (x509_crt_check_san_ip(san, cn, cn_len) == 0) { - return 0; - } - } - if (san_uri) { - if (x509_crt_check_san_uri(san, cn, cn_len) == 0) { - return 0; - } - } - - return -1; -} - -/* - * Verify the requested CN - only call this if cn is not NULL! - */ -static void x509_crt_verify_name(const mbedtls_x509_crt *crt, - const char *cn, - uint32_t *flags) -{ - const mbedtls_x509_name *name; - size_t cn_len = strlen(cn); - - if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) { - if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) { - return; - } - } else { - for (name = &crt->subject; name != NULL; name = name->next) { - if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && - x509_crt_check_cn(&name->val, cn, cn_len) == 0) { - return; - } - } - - } - - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; -} - -/* - * Merge the flags for all certs in the chain, after calling callback - */ -static int x509_crt_merge_flags_with_cb( - uint32_t *flags, - const mbedtls_x509_crt_verify_chain *ver_chain, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - unsigned i; - uint32_t cur_flags; - const mbedtls_x509_crt_verify_chain_item *cur; - - for (i = ver_chain->len; i != 0; --i) { - cur = &ver_chain->items[i-1]; - cur_flags = cur->flags; - - if (NULL != f_vrfy) { - if ((ret = f_vrfy(p_vrfy, cur->crt, (int) i-1, &cur_flags)) != 0) { - return ret; - } - } - - *flags |= cur_flags; - } - - return 0; -} - -/* - * Verify the certificate validity, with profile, restartable version - * - * This function: - * - checks the requested CN (if any) - * - checks the type and size of the EE cert's key, - * as that isn't done as part of chain building/verification currently - * - builds and verifies the chain - * - then calls the callback and merges the flags - * - * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` - * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the - * verification routine to search for trusted signers, and CRLs will - * be disabled. Otherwise, `trust_ca` will be used as the static list - * of trusted signers, and `ca_crl` will be use as the static list - * of CRLs. - */ -static int x509_crt_verify_restartable_ca_cb(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - mbedtls_x509_crt_ca_cb_t f_ca_cb, - void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, - mbedtls_x509_crt *, - int, - uint32_t *), - void *p_vrfy, - mbedtls_x509_crt_restart_ctx *rs_ctx) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_pk_type_t pk_type; - mbedtls_x509_crt_verify_chain ver_chain; - uint32_t ee_flags; - - *flags = 0; - ee_flags = 0; - x509_crt_verify_chain_reset(&ver_chain); - - if (profile == NULL) { - ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; - goto exit; - } - - /* check name if requested */ - if (cn != NULL) { - x509_crt_verify_name(crt, cn, &ee_flags); - } - - /* Check the type and size of the key */ - pk_type = mbedtls_pk_get_type(&crt->pk); - - if (x509_profile_check_pk_alg(profile, pk_type) != 0) { - ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; - } - - if (x509_profile_check_key(profile, &crt->pk) != 0) { - ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } - - /* Check the chain */ - ret = x509_crt_verify_chain(crt, trust_ca, ca_crl, - f_ca_cb, p_ca_cb, profile, - &ver_chain, rs_ctx); - - if (ret != 0) { - goto exit; - } - - /* Merge end-entity flags */ - ver_chain.items[0].flags |= ee_flags; - - /* Build final flags, calling callback on the way if any */ - ret = x509_crt_merge_flags_with_cb(flags, &ver_chain, f_vrfy, p_vrfy); - -exit: - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - mbedtls_x509_crt_free(ver_chain.trust_ca_cb_result); - mbedtls_free(ver_chain.trust_ca_cb_result); - ver_chain.trust_ca_cb_result = NULL; -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if (rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS) { - mbedtls_x509_crt_restart_free(rs_ctx); - } -#endif - - /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by - * the SSL module for authmode optional, but non-zero return from the - * callback means a fatal error so it shouldn't be ignored */ - if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - ret = MBEDTLS_ERR_X509_FATAL_ERROR; - } - - if (ret != 0) { - *flags = (uint32_t) -1; - return ret; - } - - if (*flags != 0) { - return MBEDTLS_ERR_X509_CERT_VERIFY_FAILED; - } - - return 0; -} - - -/* - * Verify the certificate validity (default profile, not restartable) - */ -int mbedtls_x509_crt_verify(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, - NULL, NULL, - &mbedtls_x509_crt_profile_default, - cn, flags, - f_vrfy, p_vrfy, NULL); -} - -/* - * Verify the certificate validity (user-chosen profile, not restartable) - */ -int mbedtls_x509_crt_verify_with_profile(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, - NULL, NULL, - profile, cn, flags, - f_vrfy, p_vrfy, NULL); -} - -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -/* - * Verify the certificate validity (user-chosen profile, CA callback, - * not restartable). - */ -int mbedtls_x509_crt_verify_with_ca_cb(mbedtls_x509_crt *crt, - mbedtls_x509_crt_ca_cb_t f_ca_cb, - void *p_ca_cb, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy) -{ - return x509_crt_verify_restartable_ca_cb(crt, NULL, NULL, - f_ca_cb, p_ca_cb, - profile, cn, flags, - f_vrfy, p_vrfy, NULL); -} -#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ - -int mbedtls_x509_crt_verify_restartable(mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy, - mbedtls_x509_crt_restart_ctx *rs_ctx) -{ - return x509_crt_verify_restartable_ca_cb(crt, trust_ca, ca_crl, - NULL, NULL, - profile, cn, flags, - f_vrfy, p_vrfy, rs_ctx); -} - - -/* - * Initialize a certificate chain - */ -void mbedtls_x509_crt_init(mbedtls_x509_crt *crt) -{ - memset(crt, 0, sizeof(mbedtls_x509_crt)); -} - -/* - * Unallocate all certificate data - */ -void mbedtls_x509_crt_free(mbedtls_x509_crt *crt) -{ - mbedtls_x509_crt *cert_cur = crt; - mbedtls_x509_crt *cert_prv; - - while (cert_cur != NULL) { - mbedtls_pk_free(&cert_cur->pk); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free(cert_cur->sig_opts); -#endif - - mbedtls_asn1_free_named_data_list_shallow(cert_cur->issuer.next); - mbedtls_asn1_free_named_data_list_shallow(cert_cur->subject.next); - mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next); - mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next); - mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next); - mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next); - - if (cert_cur->raw.p != NULL && cert_cur->own_buffer) { - mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len); - } - - cert_prv = cert_cur; - cert_cur = cert_cur->next; - - mbedtls_platform_zeroize(cert_prv, sizeof(mbedtls_x509_crt)); - if (cert_prv != crt) { - mbedtls_free(cert_prv); - } - } -} - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) -/* - * Initialize a restart context - */ -void mbedtls_x509_crt_restart_init(mbedtls_x509_crt_restart_ctx *ctx) -{ - mbedtls_pk_restart_init(&ctx->pk); - - ctx->parent = NULL; - ctx->fallback_parent = NULL; - ctx->fallback_signature_is_good = 0; - - ctx->parent_is_trusted = -1; - - ctx->in_progress = x509_crt_rs_none; - ctx->self_cnt = 0; - x509_crt_verify_chain_reset(&ctx->ver_chain); -} - -/* - * Free the components of a restart context - */ -void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx) -{ - if (ctx == NULL) { - return; - } - - mbedtls_pk_restart_free(&ctx->pk); - mbedtls_x509_crt_restart_init(ctx); -} -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - -#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/matter/mbedtls/tinycrypt/src/x509write_csr.c b/matter/mbedtls/tinycrypt/src/x509write_csr.c deleted file mode 100644 index d996052ba0..0000000000 --- a/matter/mbedtls/tinycrypt/src/x509write_csr.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * X.509 Certificate Signing Request writing - * - * 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. - */ -/* - * References: - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -#include "common.h" - -#if defined(MBEDTLS_X509_CSR_WRITE_C) - -#include "mbedtls/x509.h" -#include "mbedtls/x509_csr.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/error.h" -#include "mbedtls/oid.h" -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_USE_PSA_CRYPTO) -#include "psa/crypto.h" -#include "psa_util_internal.h" -#include "md_psa.h" -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - -#include -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#include "mbedtls/platform.h" - -void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx) -{ - memset(ctx, 0, sizeof(mbedtls_x509write_csr)); -} - -void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx) -{ - mbedtls_asn1_free_named_data_list(&ctx->subject); - mbedtls_asn1_free_named_data_list(&ctx->extensions); - - mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_csr)); -} - -void mbedtls_x509write_csr_set_md_alg(mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg) -{ - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_csr_set_key(mbedtls_x509write_csr *ctx, mbedtls_pk_context *key) -{ - ctx->key = key; -} - -int mbedtls_x509write_csr_set_subject_name(mbedtls_x509write_csr *ctx, - const char *subject_name) -{ - return mbedtls_x509_string_to_names(&ctx->subject, subject_name); -} - -int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len) -{ - return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len, - critical, val, val_len); -} - -int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx, - const mbedtls_x509_san_list *san_list) -{ - return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list); -} - -int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage) -{ - unsigned char buf[4] = { 0 }; - unsigned char *c; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - c = buf + 4; - - ret = mbedtls_asn1_write_named_bitstring(&c, buf, &key_usage, 8); - if (ret < 3 || ret > 4) { - return ret; - } - - ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE), - 0, c, (size_t) ret); - if (ret != 0) { - return ret; - } - - return 0; -} - -int mbedtls_x509write_csr_set_ns_cert_type(mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type) -{ - unsigned char buf[4] = { 0 }; - unsigned char *c; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - - c = buf + 4; - - ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8); - if (ret < 3 || ret > 4) { - return ret; - } - - ret = mbedtls_x509write_csr_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE), - 0, c, (size_t) ret); - if (ret != 0) { - return ret; - } - - return 0; -} - -static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx, - unsigned char *buf, - size_t size, - unsigned char *sig, size_t sig_size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - size_t pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - size_t hash_len; - psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg); -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - - /* Write the CSR backwards starting from the end of buf */ - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_extensions(&c, buf, - ctx->extensions)); - - if (len) { - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)); - - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_oid( - &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, - MBEDTLS_OID_SIZE(MBEDTLS_OID_PKCS9_CSR_EXT_REQ))); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - } - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)); - - MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key, - buf, c - buf)); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf, - ctx->subject)); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - - /* - * Sign the written CSR data into the sig buffer - * Note: hash errors can happen only after an internal error - */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if (psa_hash_compute(hash_alg, - c, - len, - hash, - sizeof(hash), - &hash_len) != PSA_SUCCESS) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } -#else /* MBEDTLS_USE_PSA_CRYPTO */ - ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c, len, hash); - if (ret != 0) { - return ret; - } -#endif - if ((ret = mbedtls_pk_sign(ctx->key, ctx->md_alg, hash, 0, - sig, sig_size, &sig_len, - f_rng, p_rng)) != 0) { - return ret; - } - - if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_RSA)) { - pk_alg = MBEDTLS_PK_RSA; - } else if (mbedtls_pk_can_do(ctx->key, MBEDTLS_PK_ECDSA)) { - pk_alg = MBEDTLS_PK_ECDSA; - } else { - return MBEDTLS_ERR_X509_INVALID_ALG; - } - - if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len)) != 0) { - return ret; - } - - /* - * Move the written CSR data to the start of buf to create space for - * writing the signature into buf. - */ - memmove(buf, c, len); - - /* - * Write sig and its OID into buf backwards from the end of buf. - * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len - * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, - mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len, - sig, sig_len, pk_alg)); - - /* - * Compact the space between the CSR data and signature by moving the - * CSR data to the start of the signature. - */ - c2 -= len; - memmove(c2, buf, len); - - /* ASN encode the total size and tag the CSR data with it. */ - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c2, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, - mbedtls_asn1_write_tag( - &c2, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); - - /* Zero the unused bytes at the start of buf */ - memset(buf, 0, c2 - buf); - - return (int) len; -} - -int mbedtls_x509write_csr_der(mbedtls_x509write_csr *ctx, unsigned char *buf, - size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - int ret; - unsigned char *sig; - - if ((sig = mbedtls_calloc(1, MBEDTLS_PK_SIGNATURE_MAX_SIZE)) == NULL) { - return MBEDTLS_ERR_X509_ALLOC_FAILED; - } - - ret = x509write_csr_der_internal(ctx, buf, size, - sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, - f_rng, p_rng); - - mbedtls_free(sig); - - return ret; -} - -#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" -#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_csr_pem(mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - size_t olen = 0; - - if ((ret = mbedtls_x509write_csr_der(ctx, buf, size, - f_rng, p_rng)) < 0) { - return ret; - } - - if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CSR, PEM_END_CSR, - buf + size - ret, - ret, buf, size, &olen)) != 0) { - return ret; - } - - return 0; -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CSR_WRITE_C */ From 74bdaefb163f9e596649eea3f9a4efb2a96e19dd Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:42:58 +0530 Subject: [PATCH 07/11] WIP: compilation working --- .../tinycrypt/inc/tinycrypt/tinycrypt_util.h | 4 +- matter/mbedtls/tinycrypt/src/ecc.c | 12 +++-- matter/mbedtls/tinycrypt/src/ecc_dh.c | 12 ++--- matter/mbedtls/tinycrypt/src/ecc_dsa.c | 2 + matter/mbedtls/tinycrypt/src/tinycrypt_util.c | 49 ------------------- 5 files changed, 19 insertions(+), 60 deletions(-) diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h index 73506f6bab..4f643e608e 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h @@ -10,8 +10,8 @@ void *mbedtls_platform_memset(void *, int, size_t); void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); void mbedtls_platform_random_delay(void); uint32_t mbedtls_platform_random_in_range(uint32_t num); -int mbedtls_platform_memmove(void *dst, const void *src, size_t num); -int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num); +// int mbedtls_platform_memmove(void *dst, const void *src, size_t num); +// int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num); #endif // defined(SL_MBEDTLS_USE_TINYCRYPT) #endif // TINYCRYPT_PLATFORM_UTIL_H \ No newline at end of file diff --git a/matter/mbedtls/tinycrypt/src/ecc.c b/matter/mbedtls/tinycrypt/src/ecc.c index 88f9234574..e88589003a 100644 --- a/matter/mbedtls/tinycrypt/src/ecc.c +++ b/matter/mbedtls/tinycrypt/src/ecc.c @@ -64,11 +64,13 @@ #endif #if defined(SL_MBEDTLS_USE_TINYCRYPT) -#include -#include "mbedtls/platform_util.h" -#include "mbedtls/sha256.h" #include + +#include "tinycrypt/ecc.h" +#include "tinycrypt/tinycrypt_util.h" + #include "mbedtls/platform_util.h" +#include "mbedtls/sha256.h" #if defined MBEDTLS_OPTIMIZE_TINYCRYPT_ASM #ifndef asm @@ -76,6 +78,10 @@ #endif #endif /* MBEDTLS_OPTIMIZE_TINYCRYPT_ASM */ +#if (MBEDTLS_VERSION_NUMBER >= 0x03000000) +#include "mbedtls/compat-2.x.h" +#endif + /* Parameters for curve NIST P-256 aka secp256r1 */ const uECC_word_t curve_p[NUM_ECC_WORDS] = { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index 5b992f0f35..2ee788ce1a 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -67,9 +67,12 @@ #endif #if defined(SL_MBEDTLS_USE_TINYCRYPT) +#include + #include #include -#include +#include + #include "mbedtls/platform_util.h" int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key, @@ -173,7 +176,6 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uECC_word_t _private[NUM_ECC_WORDS]; wordcount_t num_words = NUM_ECC_WORDS; wordcount_t num_bytes = NUM_ECC_BYTES; - int r = UECC_FAULT_DETECTED; /* Converting buffers to correct bit order: */ uECC_vli_bytesToNative(_private, @@ -186,13 +188,11 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, public_key + num_bytes, num_bytes); - r = EccPoint_mult_safer(_public, _public, _private); + int r = EccPoint_mult_safer(_public, _public, _private); uECC_vli_nativeToBytes(secret, num_bytes, _public); /* erasing temporary buffer used to store secret: */ - if (_private == mbedtls_platform_zeroize(_private, sizeof(_private))) { - return r; - } + mbedtls_platform_zeroize(_private, sizeof(_private)); return UECC_FAULT_DETECTED; } diff --git a/matter/mbedtls/tinycrypt/src/ecc_dsa.c b/matter/mbedtls/tinycrypt/src/ecc_dsa.c index 1084ed5e52..cfc01dc372 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dsa.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dsa.c @@ -67,6 +67,8 @@ #if defined(SL_MBEDTLS_USE_TINYCRYPT) #include #include +#include + #include "mbedtls/platform_util.h" static void bits2int(uECC_word_t *native, const uint8_t *bits, diff --git a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c index 0a7fb83fa9..c33457f3e7 100644 --- a/matter/mbedtls/tinycrypt/src/tinycrypt_util.c +++ b/matter/mbedtls/tinycrypt/src/tinycrypt_util.c @@ -207,52 +207,3 @@ void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num) mbedtls_platform_fault(); return NULL; } - -int mbedtls_platform_memmove(void *dst, const void *src, size_t num) -{ - void *ret1 = NULL; - void *ret2 = NULL; - /* The buffers can have a common part, so we cannot do a copy from a random - * location. By using a temporary buffer we can do so, but the cost of it - * is using more memory and longer transfer time. */ - void *tmp = mbedtls_calloc(1, num); - if (tmp != NULL) { - ret1 = mbedtls_platform_memcpy(tmp, src, num); - ret2 = mbedtls_platform_memcpy(dst, tmp, num); - mbedtls_free(tmp); - if (ret1 == tmp && ret2 == dst) { - return 0; - } - return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - } - - return MBEDTLS_ERR_ERROR_GENERIC_ERROR; -} - -int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num) -{ - volatile const unsigned char *A = (volatile const unsigned char *)buf1; - volatile const unsigned char *B = (volatile const unsigned char *)buf2; - volatile unsigned char diff = 0; - - /* Start from a random location and check the correct number of iterations */ - size_t i, flow_counter = 0; - size_t start_offset = 0; - if (num > 0) { - start_offset = (size_t)mbedtls_platform_random_in_range((uint32_t)num); - - for (i = start_offset; i < num; i++) { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } - - for (i = 0; i < start_offset; i++) { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } - } - /* Return 0 only when diff is 0 and flow_counter is equal to num */ - return ((int)diff | (int)(flow_counter ^ num)); -} \ No newline at end of file From 391083230127dd5d9ea5daf30865ce66d6f7f8aa Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:15:28 +0530 Subject: [PATCH 08/11] Added fix for mbedTLS 3.x --- matter/mbedtls/tinycrypt/src/ecc_dh.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/matter/mbedtls/tinycrypt/src/ecc_dh.c b/matter/mbedtls/tinycrypt/src/ecc_dh.c index 2ee788ce1a..a557ec2097 100644 --- a/matter/mbedtls/tinycrypt/src/ecc_dh.c +++ b/matter/mbedtls/tinycrypt/src/ecc_dh.c @@ -176,6 +176,7 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uECC_word_t _private[NUM_ECC_WORDS]; wordcount_t num_words = NUM_ECC_WORDS; wordcount_t num_bytes = NUM_ECC_BYTES; + int r = UECC_FAULT_DETECTED; /* Converting buffers to correct bit order: */ uECC_vli_bytesToNative(_private, @@ -188,12 +189,14 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, public_key + num_bytes, num_bytes); - int r = EccPoint_mult_safer(_public, _public, _private); + r = EccPoint_mult_safer(_public, _public, _private); uECC_vli_nativeToBytes(secret, num_bytes, _public); - + + if(r != UECC_SUCCESS) { /* erasing temporary buffer used to store secret: */ mbedtls_platform_zeroize(_private, sizeof(_private)); + } - return UECC_FAULT_DETECTED; + return r; } #endif /* SL_MBEDTLS_USE_TINYCRYPT */ From 6f5394dbcae501d2af66b02f34c0399355a62fbc Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:20:11 +0530 Subject: [PATCH 09/11] Update mbedTLS configuration --- .../si91x/siwx917/BRD4338A/autogen/sli_mbedtls_config_autogen.h | 2 +- .../si91x/siwx917/BRD4342A/autogen/sli_mbedtls_config_autogen.h | 2 +- .../si91x/siwx917/BRD4343A/autogen/sli_mbedtls_config_autogen.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/matter/si91x/siwx917/BRD4338A/autogen/sli_mbedtls_config_autogen.h b/matter/si91x/siwx917/BRD4338A/autogen/sli_mbedtls_config_autogen.h index a900af14a9..d861cf01fb 100644 --- a/matter/si91x/siwx917/BRD4338A/autogen/sli_mbedtls_config_autogen.h +++ b/matter/si91x/siwx917/BRD4338A/autogen/sli_mbedtls_config_autogen.h @@ -12,6 +12,7 @@ #define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_BASE64_C #define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_PADDING_PKCS7 #define MBEDTLS_CMAC_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C @@ -44,6 +45,5 @@ #define MBEDTLS_USE_PSA_CRYPTO #define MBEDTLS_PSA_CRYPTO_CONFIG #define MBEDTLS_PSA_CRYPTO_STORAGE_C -#define MBEDTLS_CIPHER_PADDING_PKCS7 #endif // SL_MBEDTLS_USE_TINYCRYPT #endif // SLI_MBEDTLS_CONFIG_AUTOGEN_H diff --git a/matter/si91x/siwx917/BRD4342A/autogen/sli_mbedtls_config_autogen.h b/matter/si91x/siwx917/BRD4342A/autogen/sli_mbedtls_config_autogen.h index a900af14a9..d861cf01fb 100644 --- a/matter/si91x/siwx917/BRD4342A/autogen/sli_mbedtls_config_autogen.h +++ b/matter/si91x/siwx917/BRD4342A/autogen/sli_mbedtls_config_autogen.h @@ -12,6 +12,7 @@ #define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_BASE64_C #define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_PADDING_PKCS7 #define MBEDTLS_CMAC_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C @@ -44,6 +45,5 @@ #define MBEDTLS_USE_PSA_CRYPTO #define MBEDTLS_PSA_CRYPTO_CONFIG #define MBEDTLS_PSA_CRYPTO_STORAGE_C -#define MBEDTLS_CIPHER_PADDING_PKCS7 #endif // SL_MBEDTLS_USE_TINYCRYPT #endif // SLI_MBEDTLS_CONFIG_AUTOGEN_H diff --git a/matter/si91x/siwx917/BRD4343A/autogen/sli_mbedtls_config_autogen.h b/matter/si91x/siwx917/BRD4343A/autogen/sli_mbedtls_config_autogen.h index a900af14a9..d861cf01fb 100644 --- a/matter/si91x/siwx917/BRD4343A/autogen/sli_mbedtls_config_autogen.h +++ b/matter/si91x/siwx917/BRD4343A/autogen/sli_mbedtls_config_autogen.h @@ -12,6 +12,7 @@ #define MBEDTLS_ASN1_WRITE_C #define MBEDTLS_BASE64_C #define MBEDTLS_CIPHER_C +#define MBEDTLS_CIPHER_PADDING_PKCS7 #define MBEDTLS_CMAC_C #define MBEDTLS_ECDSA_C #define MBEDTLS_ECP_C @@ -44,6 +45,5 @@ #define MBEDTLS_USE_PSA_CRYPTO #define MBEDTLS_PSA_CRYPTO_CONFIG #define MBEDTLS_PSA_CRYPTO_STORAGE_C -#define MBEDTLS_CIPHER_PADDING_PKCS7 #endif // SL_MBEDTLS_USE_TINYCRYPT #endif // SLI_MBEDTLS_CONFIG_AUTOGEN_H From dd32f62551153323f1fafd2d3251d73733cb2e7c Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Fri, 22 Nov 2024 15:48:44 +0530 Subject: [PATCH 10/11] Pending cleanup of files --- .../tinycrypt/inc/tinycrypt/constants.h | 61 -- .../inc/tinycrypt/ecc_platform_specific.h | 81 --- .../mbedtls/tinycrypt/inc/tinycrypt/utils.h | 95 --- .../tinycrypt/src/ecc_platform_specific.c | 105 --- src/core/ipv6/mld6.c | 638 ------------------ 5 files changed, 980 deletions(-) delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h delete mode 100644 matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h delete mode 100644 matter/mbedtls/tinycrypt/src/ecc_platform_specific.c delete mode 100644 src/core/ipv6/mld6.c diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h deleted file mode 100644 index 965490e00c..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/constants.h +++ /dev/null @@ -1,61 +0,0 @@ -/* constants.h - TinyCrypt interface to constants */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief -- Interface to constants. - * - */ - -#ifndef __TC_CONSTANTS_H__ -#define __TC_CONSTANTS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifndef NULL -#define NULL ((void *)0) -#endif - -#define TC_CRYPTO_SUCCESS 1 -#define TC_CRYPTO_FAIL 0 - -#define TC_ZERO_BYTE 0x00 - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_CONSTANTS_H__ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h deleted file mode 100644 index e2c882356e..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/ecc_platform_specific.h +++ /dev/null @@ -1,81 +0,0 @@ -/* uECC_platform_specific.h - Interface to platform specific functions*/ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * uECC_platform_specific.h -- Interface to platform specific functions - */ - -#ifndef __UECC_PLATFORM_SPECIFIC_H_ -#define __UECC_PLATFORM_SPECIFIC_H_ - -/* - * The RNG function should fill 'size' random bytes into 'dest'. It should - * return 1 if 'dest' was filled with random data, or 0 if the random data could - * not be generated. The filled-in values should be either truly random, or from - * a cryptographically-secure PRNG. - * - * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) - * before calling uECC_make_key() or uECC_sign(). - * - * Setting a cryptographically-secure PRNG function improves the resistance to - * side-channel attacks for uECC_shared_secret(). - * - * A correct PRNG function is set by default (default_RNG_defined = 1) and works - * for some platforms, such as Unix and Linux. For other platforms, you may need - * to provide another PRNG function. -*/ -#define default_RNG_defined 1 - -int default_CSPRNG(uint8_t *dest, unsigned int size); - -#endif /* __UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h deleted file mode 100644 index bab5c3202e..0000000000 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/utils.h +++ /dev/null @@ -1,95 +0,0 @@ -/* utils.h - TinyCrypt interface to platform-dependent run-time operations */ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @file - * @brief Interface to platform-dependent run-time operations. - * - */ - -#ifndef __TC_UTILS_H__ -#define __TC_UTILS_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Copy the the buffer 'from' to the buffer 'to'. - * @return returns TC_CRYPTO_SUCCESS (1) - * returns TC_CRYPTO_FAIL (0) if: - * from_len > to_len. - * - * @param to OUT -- destination buffer - * @param to_len IN -- length of destination buffer - * @param from IN -- origin buffer - * @param from_len IN -- length of origin buffer - */ -unsigned int _copy(uint8_t *to, unsigned int to_len, - const uint8_t *from, unsigned int from_len); - -/** - * @brief Set the value 'val' into the buffer 'to', 'len' times. - * - * @param to OUT -- destination buffer - * @param val IN -- value to be set in 'to' - * @param len IN -- number of times the value will be copied - */ -void _set(void *to, uint8_t val, unsigned int len); - -/* - * @brief AES specific doubling function, which utilizes - * the finite field used by AES. - * @return Returns a^2 - * - * @param a IN/OUT -- value to be doubled - */ -uint8_t _double_byte(uint8_t a); - -/* - * @brief Constant-time algorithm to compare if two sequences of bytes are equal - * @return Returns 0 if equal, and non-zero otherwise - * - * @param a IN -- sequence of bytes a - * @param b IN -- sequence of bytes b - * @param size IN -- size of sequences a and b - */ -int _compare(const uint8_t *a, const uint8_t *b, size_t size); - -#ifdef __cplusplus -} -#endif - -#endif /* __TC_UTILS_H__ */ diff --git a/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c b/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c deleted file mode 100644 index 1867988f99..0000000000 --- a/matter/mbedtls/tinycrypt/src/ecc_platform_specific.c +++ /dev/null @@ -1,105 +0,0 @@ -/* uECC_platform_specific.c - Implementation of platform specific functions*/ - -/* Copyright (c) 2014, Kenneth MacKay - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE.*/ - -/* - * Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * uECC_platform_specific.c -- Implementation of platform specific functions - */ - - -#if defined(unix) || defined(__linux__) || defined(__unix__) || \ - defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \ - defined(uECC_POSIX) - -/* Some POSIX-like system with /dev/urandom or /dev/random. */ -#include -#include -#include - -#include - -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif - -int default_CSPRNG(uint8_t *dest, unsigned int size) { - - /* input sanity check: */ - if (dest == (uint8_t *) 0 || (size <= 0)) - return 0; - - int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); - if (fd == -1) { - fd = open("/dev/random", O_RDONLY | O_CLOEXEC); - if (fd == -1) { - return 0; - } - } - - char *ptr = (char *)dest; - size_t left = (size_t) size; - while (left > 0) { - ssize_t bytes_read = read(fd, ptr, left); - if (bytes_read <= 0) { // read failed - close(fd); - return 0; - } - left -= bytes_read; - ptr += bytes_read; - } - - close(fd); - return 1; -} - -#endif /* platform */ - diff --git a/src/core/ipv6/mld6.c b/src/core/ipv6/mld6.c deleted file mode 100644 index 091c5ad3b1..0000000000 --- a/src/core/ipv6/mld6.c +++ /dev/null @@ -1,638 +0,0 @@ -/** - * @file - * Multicast listener discovery - * - * @defgroup mld6 MLD6 - * @ingroup ip6 - * Multicast listener discovery for IPv6. Aims to be compliant with RFC 2710. - * No support for MLDv2.\n - * Note: The allnodes (ff01::1, ff02::1) group is assumed be received by your - * netif since it must always be received for correct IPv6 operation (e.g. - * SLAAC). Ensure the netif filters are configured accordingly!\n The netif - * flags also need NETIF_FLAG_MLD6 flag set to enable MLD6 on a netif - * ("netif->flags |= NETIF_FLAG_MLD6;").\n To be called from TCPIP thread. - */ - -/* - * Copyright (c) 2010 Inico Technologies Ltd. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Ivan Delamer - * - * - * Please coordinate changes and requests with Ivan Delamer - * - */ - -/* Based on igmp.c implementation of igmp v2 protocol */ - -#include "lwip/opt.h" - -#if LWIP_IPV6 && \ - LWIP_IPV6_MLD /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/icmp6.h" -#include "lwip/inet_chksum.h" -#include "lwip/ip.h" -#include "lwip/ip6.h" -#include "lwip/ip6_addr.h" -#include "lwip/memp.h" -#include "lwip/mld6.h" -#include "lwip/netif.h" -#include "lwip/pbuf.h" -#include "lwip/prot/mld6.h" -#include "lwip/stats.h" - -#include - -/* - * MLD constants - */ -#define MLD6_HL 1 -#define MLD6_JOIN_DELAYING_MEMBER_TMR_MS (500) - -#define MLD6_GROUP_NON_MEMBER 0 -#define MLD6_GROUP_DELAYING_MEMBER 1 -#define MLD6_GROUP_IDLE_MEMBER 2 - -/* Forward declarations. */ -static struct mld_group *mld6_new_group(struct netif *ifp, - const ip6_addr_t *addr); -static err_t mld6_remove_group(struct netif *netif, struct mld_group *group); -static void mld6_delayed_report(struct mld_group *group, u16_t maxresp); -static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type); - -#if SL_LWIP_MLD6_TIMERS_ONDEMAND -#include "lwip/timeouts.h" -#include "stdbool.h" -static bool is_tmr_start = false; -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ - -/** - * Stop MLD processing on interface - * - * @param netif network interface on which stop MLD processing - */ -err_t mld6_stop(struct netif *netif) { - struct mld_group *group = netif_mld6_data(netif); - - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, NULL); - - while (group != NULL) { - struct mld_group *next = group->next; /* avoid use-after-free below */ - - /* disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, &(group->group_address), - NETIF_DEL_MAC_FILTER); - } - - /* free group */ - memp_free(MEMP_MLD6_GROUP, group); - - /* move to "next" */ - group = next; - } - return ERR_OK; -} - -/** - * Report MLD memberships for this interface - * - * @param netif network interface on which report MLD memberships - */ -void mld6_report_groups(struct netif *netif) { - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - group = group->next; - } -} - -/** - * Search for a group that is joined on a netif - * - * @param ifp the network interface for which to look - * @param addr the group ipv6 address to search for - * @return a struct mld_group* if the group has been found, - * NULL if the group wasn't found. - */ -struct mld_group *mld6_lookfor_group(struct netif *ifp, - const ip6_addr_t *addr) { - struct mld_group *group = netif_mld6_data(ifp); - - while (group != NULL) { - if (ip6_addr_cmp(&(group->group_address), addr)) { - return group; - } - group = group->next; - } - - return NULL; -} - -/** - * create a new group - * - * @param ifp the network interface for which to create - * @param addr the new group ipv6 - * @return a struct mld_group*, - * NULL on memory error. - */ -static struct mld_group *mld6_new_group(struct netif *ifp, - const ip6_addr_t *addr) { - struct mld_group *group; - - group = (struct mld_group *)memp_malloc(MEMP_MLD6_GROUP); - if (group != NULL) { - ip6_addr_set(&(group->group_address), addr); - group->timer = 0; /* Not running */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - group->use = 0; - group->next = netif_mld6_data(ifp); - - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, group); - } - - return group; -} - -/** - * Remove a group from the mld_group_list, but do not free it yet - * - * @param group the group to remove - * @return ERR_OK if group was removed from the list, an err_t otherwise - */ -static err_t mld6_remove_group(struct netif *netif, struct mld_group *group) { - err_t err = ERR_OK; - - /* Is it the first group? */ - if (netif_mld6_data(netif) == group) { - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_MLD6, - group->next); - } else { - /* look for group further down the list */ - struct mld_group *tmpGroup; - for (tmpGroup = netif_mld6_data(netif); tmpGroup != NULL; - tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not find group */ - if (tmpGroup == NULL) { - err = ERR_ARG; - } - } - - return err; -} - -/** - * Process an input MLD message. Called by icmp6_input. - * - * @param p the mld packet, p->payload pointing to the icmpv6 header - * @param inp the netif on which this packet was received - */ -void mld6_input(struct pbuf *p, struct netif *inp) { - struct mld_header *mld_hdr; - struct mld_group *group; - - MLD6_STATS_INC(mld6.recv); - - /* Check that mld header fits in packet. */ - if (p->len < sizeof(struct mld_header)) { - /* @todo debug message */ - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - MLD6_STATS_INC(mld6.drop); - return; - } - - mld_hdr = (struct mld_header *)p->payload; - - switch (mld_hdr->type) { - case ICMP6_TYPE_MLQ: /* Multicast listener query. */ - /* Is it a general query? */ - if (ip6_addr_isallnodes_linklocal(ip6_current_dest_addr()) && - ip6_addr_isany(&(mld_hdr->multicast_address))) { - MLD6_STATS_INC(mld6.rx_general); - /* Report all groups, except all nodes group, and if-local groups. */ - group = netif_mld6_data(inp); - while (group != NULL) { - if ((!(ip6_addr_ismulticast_iflocal(&(group->group_address)))) && - (!(ip6_addr_isallnodes_linklocal(&(group->group_address))))) { - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - group = group->next; - } - } else { - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_group); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* Schedule a report. */ - mld6_delayed_report(group, mld_hdr->max_resp_delay); - } - } - break; /* ICMP6_TYPE_MLQ */ - case ICMP6_TYPE_MLR: /* Multicast listener report. */ - /* Have we joined this group? - * We use IP6 destination address to have a memory aligned copy. - * mld_hdr->multicast_address should be the same. */ - MLD6_STATS_INC(mld6.rx_report); - group = mld6_lookfor_group(inp, ip6_current_dest_addr()); - if (group != NULL) { - /* If we are waiting to report, cancel it. */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - group->timer = 0; /* stopped */ - group->group_state = MLD6_GROUP_IDLE_MEMBER; - group->last_reporter_flag = 0; - } - } - break; /* ICMP6_TYPE_MLR */ - case ICMP6_TYPE_MLD: /* Multicast listener done. */ - /* Do nothing, router will query us. */ - break; /* ICMP6_TYPE_MLD */ - default: - MLD6_STATS_INC(mld6.proterr); - MLD6_STATS_INC(mld6.drop); - break; - } - - pbuf_free(p); -} - -/** - * @ingroup mld6 - * Join a group on one or all network interfaces. - * - * If the group is to be joined on all interfaces, the given group address must - * not have a zone set (i.e., it must have its zone index set to IP6_NO_ZONE). - * If the group is to be joined on one particular interface, the given group - * address may or may not have a zone set. - * - * @param srcaddr ipv6 address (zoned) of the network interface which should - * join a new group. If IP6_ADDR_ANY6, join on all netifs - * @param groupaddr the ipv6 address of the group to join (possibly but not - * necessarily zoned) - * @return ERR_OK if group was joined on the netif(s), an err_t otherwise - */ -err_t mld6_joingroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - LWIP_ASSERT_CORE_LOCKED(); - - /* loop through netif's */ - NETIF_FOREACH(netif) { - /* Should we join this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err = mld6_joingroup_netif(netif, groupaddr); - if (err != ERR_OK) { - return err; - } - } - } - - return err; -} - -/** - * @ingroup mld6 - * Join a group on a network interface. - * - * @param netif the network interface which should join a new group. - * @param groupaddr the ipv6 address of the group to join (possibly but not - * necessarily zoned) - * @return ERR_OK if group was joined on the netif, an err_t otherwise - */ -err_t mld6_joingroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) { - struct mld_group *group; -#if LWIP_IPV6_SCOPES - ip6_addr_t ip6addr; - - /* If the address has a particular scope but no zone set, use the netif to - * set one now. Within the mld6 module, all addresses are properly zoned. */ - if (ip6_addr_lacks_zone(groupaddr, IP6_MULTICAST)) { - ip6_addr_set(&ip6addr, groupaddr); - ip6_addr_assign_zone(&ip6addr, IP6_MULTICAST, netif); - groupaddr = &ip6addr; - } - IP6_ADDR_ZONECHECK_NETIF(groupaddr, netif); -#endif /* LWIP_IPV6_SCOPES */ - - LWIP_ASSERT_CORE_LOCKED(); - - /* find group or create a new one if not found */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group == NULL) { - /* Joining a new group. Create a new group entry. */ - group = mld6_new_group(netif, groupaddr); - if (group == NULL) { - return ERR_MEM; - } - - /* Activate this address on the MAC layer. */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_ADD_MAC_FILTER); - } - - /* Report our membership. */ - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - mld6_delayed_report(group, MLD6_JOIN_DELAYING_MEMBER_TMR_MS); - } - - /* Increment group use */ - group->use++; - return ERR_OK; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * Zoning of address follows the same rules as @ref mld6_joingroup. - * - * @param srcaddr ipv6 address (zoned) of the network interface which should - * leave the group. If IP6_ADDR_ANY6, leave on all netifs - * @param groupaddr the ipv6 address of the group to leave (possibly, but not - * necessarily zoned) - * @return ERR_OK if group was left on the netif(s), an err_t otherwise - */ -err_t mld6_leavegroup(const ip6_addr_t *srcaddr, const ip6_addr_t *groupaddr) { - err_t err = ERR_VAL; /* no matching interface */ - struct netif *netif; - - LWIP_ASSERT_CORE_LOCKED(); - - /* loop through netif's */ - NETIF_FOREACH(netif) { - /* Should we leave this interface ? */ - if (ip6_addr_isany(srcaddr) || - netif_get_ip6_addr_match(netif, srcaddr) >= 0) { - err_t res = mld6_leavegroup_netif(netif, groupaddr); - if (err != ERR_OK) { - /* Store this result if we have not yet gotten a success */ - err = res; - } - } - } - - return err; -} - -/** - * @ingroup mld6 - * Leave a group on a network interface. - * - * @param netif the network interface which should leave the group. - * @param groupaddr the ipv6 address of the group to leave (possibly, but not - * necessarily zoned) - * @return ERR_OK if group was left on the netif, an err_t otherwise - */ -err_t mld6_leavegroup_netif(struct netif *netif, const ip6_addr_t *groupaddr) { - struct mld_group *group; -#if LWIP_IPV6_SCOPES - ip6_addr_t ip6addr; - - if (ip6_addr_lacks_zone(groupaddr, IP6_MULTICAST)) { - ip6_addr_set(&ip6addr, groupaddr); - ip6_addr_assign_zone(&ip6addr, IP6_MULTICAST, netif); - groupaddr = &ip6addr; - } - IP6_ADDR_ZONECHECK_NETIF(groupaddr, netif); -#endif /* LWIP_IPV6_SCOPES */ - - LWIP_ASSERT_CORE_LOCKED(); - - /* find group */ - group = mld6_lookfor_group(netif, groupaddr); - - if (group != NULL) { - /* Leave if there is no other use of the group */ - if (group->use <= 1) { - /* Remove the group from the list */ - mld6_remove_group(netif, group); - - /* If we are the last reporter for this group */ - if (group->last_reporter_flag) { - MLD6_STATS_INC(mld6.tx_leave); - mld6_send(netif, group, ICMP6_TYPE_MLD); - } - - /* Disable the group at the MAC level */ - if (netif->mld_mac_filter != NULL) { - netif->mld_mac_filter(netif, groupaddr, NETIF_DEL_MAC_FILTER); - } - - /* free group struct */ - memp_free(MEMP_MLD6_GROUP, group); - } else { - /* Decrement group use */ - group->use--; - } - - /* Left group */ - return ERR_OK; - } - - /* Group not found */ - return ERR_VAL; -} - -#if SL_LWIP_MLD6_TIMERS_ONDEMAND -static void mld6_timeout_cb(void *arg) { - LWIP_UNUSED_ARG(arg); - - mld6_tmr(); -} -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ -/** - * Periodic timer for mld processing. Must be called every - * MLD6_TMR_INTERVAL milliseconds (100). - * - * When a delaying member expires, a membership report is sent. - */ -void mld6_tmr(void) { - struct netif *netif; -#if SL_LWIP_MLD6_TIMERS_ONDEMAND - bool tmr_restart = false; -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ - - NETIF_FOREACH(netif) { - struct mld_group *group = netif_mld6_data(netif); - - while (group != NULL) { - if (group->timer > 0) { - group->timer--; - if (group->timer == 0) { - /* If the state is MLD6_GROUP_DELAYING_MEMBER then we send a report - * for this group */ - if (group->group_state == MLD6_GROUP_DELAYING_MEMBER) { - MLD6_STATS_INC(mld6.tx_report); - mld6_send(netif, group, ICMP6_TYPE_MLR); - group->group_state = MLD6_GROUP_IDLE_MEMBER; - } - } -#if SL_LWIP_MLD6_TIMERS_ONDEMAND - else { - tmr_restart = true; - } -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ - } - group = group->next; - } - } -#if SL_LWIP_MLD6_TIMERS_ONDEMAND - if (tmr_restart) { - sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); - } else { - sys_untimeout(mld6_timeout_cb, NULL); - is_tmr_start = false; - } -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ -} - -/** - * Schedule a delayed membership report for a group - * - * @param group the mld_group for which "delaying" membership report - * should be sent - * @param maxresp_in the max resp delay provided in the query - */ -static void mld6_delayed_report(struct mld_group *group, u16_t maxresp_in) { - /* Convert maxresp from milliseconds to tmr ticks */ - u16_t maxresp = maxresp_in / MLD6_TMR_INTERVAL; - if (maxresp == 0) { - maxresp = 1; - } - -#ifdef LWIP_RAND - /* Randomize maxresp. (if LWIP_RAND is supported) */ - maxresp = (u16_t)(LWIP_RAND() % maxresp); - if (maxresp == 0) { - maxresp = 1; - } -#endif /* LWIP_RAND */ - - /* Apply timer value if no report has been scheduled already. */ - if ((group->group_state == MLD6_GROUP_IDLE_MEMBER) || - ((group->group_state == MLD6_GROUP_DELAYING_MEMBER) && - ((group->timer == 0) || (maxresp < group->timer)))) { - group->timer = maxresp; - group->group_state = MLD6_GROUP_DELAYING_MEMBER; -#if SL_LWIP_MLD6_TIMERS_ONDEMAND - if (!is_tmr_start) { - sys_timeout(MLD6_TMR_INTERVAL, mld6_timeout_cb, NULL); - is_tmr_start = true; - } -#endif /* SL_LWIP_MLD6_TIMERS_ONDEMAND */ - } -} - -/** - * Send a MLD message (report or done). - * - * An IPv6 hop-by-hop options header with a router alert option - * is prepended. - * - * @param group the group to report or quit - * @param type ICMP6_TYPE_MLR (report) or ICMP6_TYPE_MLD (done) - */ -static void mld6_send(struct netif *netif, struct mld_group *group, u8_t type) { - struct mld_header *mld_hdr; - struct pbuf *p; - const ip6_addr_t *src_addr; - - /* Allocate a packet. Size is MLD header + IPv6 Hop-by-hop options header. */ - p = pbuf_alloc(PBUF_IP, sizeof(struct mld_header) + MLD6_HBH_HLEN, PBUF_RAM); - if (p == NULL) { - MLD6_STATS_INC(mld6.memerr); - return; - } - - /* Move to make room for Hop-by-hop options header. */ - if (pbuf_remove_header(p, MLD6_HBH_HLEN)) { - pbuf_free(p); - MLD6_STATS_INC(mld6.lenerr); - return; - } - - /* Select our source address. */ - if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) { - /* This is a special case, when we are performing duplicate address - * detection. We must join the multicast group, but we don't have a valid - * address yet. */ - src_addr = IP6_ADDR_ANY6; - } else { - /* Use link-local address as source address. */ - src_addr = netif_ip6_addr(netif, 0); - } - - /* MLD message header pointer. */ - mld_hdr = (struct mld_header *)p->payload; - - /* Set fields. */ - mld_hdr->type = type; - mld_hdr->code = 0; - mld_hdr->chksum = 0; - mld_hdr->max_resp_delay = 0; - mld_hdr->reserved = 0; - ip6_addr_copy_to_packed(mld_hdr->multicast_address, group->group_address); - -#if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { - mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, - &(group->group_address)); - } -#endif /* CHECKSUM_GEN_ICMP6 */ - - /* Add hop-by-hop headers options: router alert with MLD value. */ - ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); - - if (type == ICMP6_TYPE_MLR) { - /* Remember we were the last to report */ - group->last_reporter_flag = 1; - } - - /* Send the packet out. */ - MLD6_STATS_INC(mld6.xmit); - ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, - &(group->group_address), MLD6_HL, 0, IP6_NEXTH_HOPBYHOP, netif); - pbuf_free(p); -} - -#endif /* LWIP_IPV6 */ From e7db807f70f6df75ced4f72f0bfd931ca968c546 Mon Sep 17 00:00:00 2001 From: Rohan Sahay <103027015+rosahay-silabs@users.noreply.github.com> Date: Mon, 25 Nov 2024 18:06:19 +0530 Subject: [PATCH 11/11] Address comments --- matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h index 4f643e608e..60acb07cb3 100644 --- a/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h +++ b/matter/mbedtls/tinycrypt/inc/tinycrypt/tinycrypt_util.h @@ -4,14 +4,10 @@ #include #include -#if defined(SL_MBEDTLS_USE_TINYCRYPT) void mbedtls_platform_random_buf(uint8_t *buf, size_t len); void *mbedtls_platform_memset(void *, int, size_t); void *mbedtls_platform_memcpy(void *dst, const void *src, size_t num); void mbedtls_platform_random_delay(void); uint32_t mbedtls_platform_random_in_range(uint32_t num); -// int mbedtls_platform_memmove(void *dst, const void *src, size_t num); -// int mbedtls_platform_memequal(const void *buf1, const void *buf2, size_t num); -#endif // defined(SL_MBEDTLS_USE_TINYCRYPT) #endif // TINYCRYPT_PLATFORM_UTIL_H \ No newline at end of file