Return-Path: X-Original-To: apmail-mynewt-commits-archive@minotaur.apache.org Delivered-To: apmail-mynewt-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 4286518847 for ; Thu, 7 Apr 2016 01:37:09 +0000 (UTC) Received: (qmail 61106 invoked by uid 500); 7 Apr 2016 01:37:09 -0000 Delivered-To: apmail-mynewt-commits-archive@mynewt.apache.org Received: (qmail 61074 invoked by uid 500); 7 Apr 2016 01:37:09 -0000 Mailing-List: contact commits-help@mynewt.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@mynewt.incubator.apache.org Delivered-To: mailing list commits@mynewt.incubator.apache.org Received: (qmail 61065 invoked by uid 99); 7 Apr 2016 01:37:09 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Apr 2016 01:37:09 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id BC0B1C0DC8 for ; Thu, 7 Apr 2016 01:37:08 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.216 X-Spam-Level: X-Spam-Status: No, score=-4.216 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.996] autolearn=disabled Received: from mx2-lw-us.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id 2pGZO9OdPxI5 for ; Thu, 7 Apr 2016 01:37:07 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx2-lw-us.apache.org (ASF Mail Server at mx2-lw-us.apache.org) with SMTP id 4C3955FAD3 for ; Thu, 7 Apr 2016 01:37:06 +0000 (UTC) Received: (qmail 61006 invoked by uid 99); 7 Apr 2016 01:37:05 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Apr 2016 01:37:05 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id AF0D8E08B6; Thu, 7 Apr 2016 01:37:05 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: marko@apache.org To: commits@mynewt.incubator.apache.org Date: Thu, 07 Apr 2016 01:37:06 -0000 Message-Id: <365915f35c4c4e6b92c44852837a5e05@git.apache.org> In-Reply-To: <7238fe0c328b42409b87b332e5bebce1@git.apache.org> References: <7238fe0c328b42409b87b332e5bebce1@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/2] incubator-mynewt-core git commit: Support image signatures as ECDSA224. Support image signatures as ECDSA224. Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/855a6afe Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/855a6afe Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/855a6afe Branch: refs/heads/develop Commit: 855a6afe0b643dee6cc30fb1190f5e28d1e1b557 Parents: 03a60f6 Author: Marko Kiiskila Authored: Wed Apr 6 18:32:55 2016 -0700 Committer: Marko Kiiskila Committed: Wed Apr 6 18:34:47 2016 -0700 ---------------------------------------------------------------------- libs/bootutil/include/bootutil/image.h | 2 + libs/bootutil/pkg.yml | 3 +- libs/bootutil/src/bootutil_priv.h | 3 + libs/bootutil/src/image_ec.c | 118 ++++++++++++++++++ libs/bootutil/src/image_rsa.c | 141 +++++++++++++++++++++ libs/bootutil/src/image_validate.c | 186 ++++++---------------------- 6 files changed, 307 insertions(+), 146 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/include/bootutil/image.h ---------------------------------------------------------------------- diff --git a/libs/bootutil/include/bootutil/image.h b/libs/bootutil/include/bootutil/image.h index e1b94bf..cf5ae34 100644 --- a/libs/bootutil/include/bootutil/image.h +++ b/libs/bootutil/include/bootutil/image.h @@ -31,6 +31,7 @@ #define IMAGE_F_PIC 0x00000001 #define IMAGE_F_SHA256 0x00000002 /* Image contains hash TLV */ #define IMAGE_F_PKCS15_RSA2048_SHA256 0x00000004 /* PKCS15 w/RSA and SHA */ +#define IMAGE_F_ECDSA224_SHA256 0x00000008 /* ECDSA256 over SHA256 */ #define IMAGE_HEADER_SIZE 32 @@ -39,6 +40,7 @@ */ #define IMAGE_TLV_SHA256 1 /* SHA256 of image hdr and body */ #define IMAGE_TLV_RSA2048 2 /* RSA2048 of hash output */ +#define IMAGE_TLV_ECDSA224 3 /* ECDSA of hash output */ struct image_version { uint8_t iv_major; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/pkg.yml ---------------------------------------------------------------------- diff --git a/libs/bootutil/pkg.yml b/libs/bootutil/pkg.yml index 2c334bc..c1bd59a 100644 --- a/libs/bootutil/pkg.yml +++ b/libs/bootutil/pkg.yml @@ -32,4 +32,5 @@ pkg.deps: - libs/mbedtls - hw/hal -pkg.cflags.IMAGE_KEYS: -DIMAGE_SIGNATURES +pkg.cflags.IMAGE_KEYS_RSA: -DIMAGE_SIGNATURES_RSA +pkg.cflags.IMAGE_KEYS_EC: -DIMAGE_SIGNATURES_EC http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/src/bootutil_priv.h ---------------------------------------------------------------------- diff --git a/libs/bootutil/src/bootutil_priv.h b/libs/bootutil/src/bootutil_priv.h index e9680c7..13e259e 100644 --- a/libs/bootutil/src/bootutil_priv.h +++ b/libs/bootutil/src/bootutil_priv.h @@ -71,5 +71,8 @@ int boot_write_status(const struct boot_status *status, int num_areas); void boot_clear_status(void); +int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen, + uint8_t key_id); + #endif http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/src/image_ec.c ---------------------------------------------------------------------- diff --git a/libs/bootutil/src/image_ec.c b/libs/bootutil/src/image_ec.c new file mode 100644 index 0000000..6b21ab2 --- /dev/null +++ b/libs/bootutil/src/image_ec.c @@ -0,0 +1,118 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +#ifdef IMAGE_SIGNATURES_EC +#include + +#include +#include +#include +#include + +#include "bootutil_priv.h" + +/* + * Declaring these like this adds NULL termination. + */ +static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED; +static const uint8_t ec_secp224r1_oid[] = MBEDTLS_OID_EC_GRP_SECP224R1; + +/* + * Parse the public key used for signing. Simple RSA format. + */ +static int +bootutil_parse_eckey(mbedtls_ecdsa_context *ctx, uint8_t **p, uint8_t *end) +{ + size_t len; + mbedtls_asn1_buf alg; + mbedtls_asn1_buf param; + + if (mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { + return -1; + } + end = *p + len; + + if (mbedtls_asn1_get_alg(p, end, &alg, ¶m)) { + return -2; + } + if (alg.len != sizeof(ec_pubkey_oid) - 1 || + memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) { + return -3; + } + if (param.len != sizeof(ec_secp224r1_oid) - 1|| + memcmp(param.p, ec_secp224r1_oid, sizeof(ec_secp224r1_oid) - 1)) { + return -4; + } + + if (mbedtls_ecp_group_load_secp224r1(&ctx->grp)) { + return -5; + } + + if (mbedtls_asn1_get_bitstring_null(p, end, &len)) { + return -6; + } + if (*p + len != end) { + return -7; + } + + if (mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, *p, end - *p)) { + return -8; + } + + if (mbedtls_ecp_check_pubkey(&ctx->grp, &ctx->Q)) { + return -9; + } + return 0; +} + +static int +bootutil_cmp_sig(mbedtls_ecdsa_context *ctx, uint8_t *hash, uint32_t hlen, + uint8_t *sig, int slen) +{ + return mbedtls_ecdsa_read_signature(ctx, hash, hlen, sig, slen); +} + +int +bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen, + uint8_t key_id) +{ + int rc; + uint8_t *cp; + uint8_t *end; + mbedtls_ecdsa_context ctx; + + mbedtls_ecdsa_init(&ctx); + + cp = (uint8_t *)bootutil_keys[key_id].key; + end = cp + *bootutil_keys[key_id].len; + + rc = bootutil_parse_eckey(&ctx, &cp, end); + if (rc) { + return -1; + } + + while (sig[slen - 1] == '\0') { + slen--; + } + rc = bootutil_cmp_sig(&ctx, hash, hlen, sig, slen); + mbedtls_ecdsa_free(&ctx); + + return rc; +} +#endif /* IMAGE_SIGNATURES_EC */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/src/image_rsa.c ---------------------------------------------------------------------- diff --git a/libs/bootutil/src/image_rsa.c b/libs/bootutil/src/image_rsa.c new file mode 100644 index 0000000..8f02329 --- /dev/null +++ b/libs/bootutil/src/image_rsa.c @@ -0,0 +1,141 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +#ifdef IMAGE_SIGNATURES_RSA +#include + +#include +#include + +#include "bootutil_priv.h" + +static const uint8_t sha256_oid[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 +}; + +/* + * Parse the public key used for signing. Simple RSA format. + */ +static int +bootutil_parse_rsakey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end) +{ + int rc; + size_t len; + + if ((rc = mbedtls_asn1_get_tag(p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { + return -1; + } + + if (*p + len != end) { + return -2; + } + + if ((rc = mbedtls_asn1_get_mpi(p, end, &ctx->N)) != 0 || + (rc = mbedtls_asn1_get_mpi(p, end, &ctx->E)) != 0) { + return -3; + } + + if (*p != end) { + return -4; + } + + if ((rc = mbedtls_rsa_check_pubkey(ctx)) != 0) { + return -5; + } + + ctx->len = mbedtls_mpi_size(&ctx->N); + + return 0; +} + +/* + * PKCS1.5 using RSA2048 computed over SHA256. + */ +static int +bootutil_cmp_rsasig(mbedtls_rsa_context *ctx, uint8_t *hash, uint32_t hlen, + uint8_t *sig) +{ + uint8_t buf[MBEDTLS_MPI_MAX_SIZE]; + uint8_t *p; + + if (ctx->len != 256) { + return -1; + } + + if (mbedtls_rsa_public(ctx, sig, buf)) { + return -1; + } + + p = buf; + + if (*p++ != 0 || *p++ != MBEDTLS_RSA_SIGN) { + return -1; + } + + while (*p != 0) { + if (p >= buf + ctx->len - 1 || *p != 0xFF) { + return -1; + } + p++; + } + p++; + + if ((p - buf) + sizeof(sha256_oid) + hlen != ctx->len) { + return -1; + } + + if (memcmp(p, sha256_oid, sizeof(sha256_oid))) { + return -1; + } + p += sizeof(sha256_oid); + + if (memcmp(p, hash, hlen)) { + return -1; + } + + return 0; +} + +int +bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen, + uint8_t key_id) +{ + mbedtls_rsa_context ctx; + int rc; + uint8_t *cp; + uint8_t *end; + + mbedtls_rsa_init(&ctx, 0, 0); + + cp = (uint8_t *)bootutil_keys[key_id].key; + end = cp + *bootutil_keys[key_id].len; + + rc = bootutil_parse_rsakey(&ctx, &cp, end); + if (rc || slen != ctx.len) { + mbedtls_rsa_free(&ctx); + return rc; + } + rc = bootutil_cmp_rsasig(&ctx, hash, hlen, sig); + mbedtls_rsa_free(&ctx); + + return rc; +} +#endif /* IMAGE_SIGNATURES_RSA */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/855a6afe/libs/bootutil/src/image_validate.c ---------------------------------------------------------------------- diff --git a/libs/bootutil/src/image_validate.c b/libs/bootutil/src/image_validate.c index 9307640..b491790 100644 --- a/libs/bootutil/src/image_validate.c +++ b/libs/bootutil/src/image_validate.c @@ -24,21 +24,14 @@ #include #include -#ifdef IMAGE_SIGNATURES #include -#endif #include #include +#include #include -#ifdef IMAGE_SIGNATURES -static const uint8_t sha256_oid[] = { - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, - 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, - 0x00, 0x04, 0x20 -}; -#endif +#include "bootutil_priv.h" /* * Compute SHA256 over the image. @@ -79,117 +72,6 @@ bootutil_img_hash(struct image_header *hdr, uint8_t flash_id, uint32_t addr, return 0; } -#ifdef IMAGE_SIGNATURES -/* - * Parse the public key used for signing. Simple RSA format. - */ -static int -bootutil_parse_rsakey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end) -{ - int rc; - size_t len; - - if ((rc = mbedtls_asn1_get_tag(p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - return -1; - } - - if (*p + len != end) { - return -2; - } - - if ((rc = mbedtls_asn1_get_mpi(p, end, &ctx->N)) != 0 || - (rc = mbedtls_asn1_get_mpi(p, end, &ctx->E)) != 0) { - return -3; - } - - if (*p != end) { - return -4; - } - - if ((rc = mbedtls_rsa_check_pubkey(ctx)) != 0) { - return -5; - } - - ctx->len = mbedtls_mpi_size(&ctx->N); - - return 0; -} - -/* - * PKCS1.5 using RSA2048 computed over SHA256. - */ -static int -bootutil_cmp_rsasig(mbedtls_rsa_context *ctx, uint8_t *hash, uint32_t hlen, - uint8_t *sig) -{ - uint8_t buf[MBEDTLS_MPI_MAX_SIZE]; - uint8_t *p; - - if (ctx->len != 256) { - return -1; - } - - if (mbedtls_rsa_public(ctx, sig, buf)) { - return -1; - } - - p = buf; - - if (*p++ != 0 || *p++ != MBEDTLS_RSA_SIGN) { - return -1; - } - - while (*p != 0) { - if (p >= buf + ctx->len - 1 || *p != 0xFF) { - return -1; - } - p++; - } - p++; - - if ((p - buf) + sizeof(sha256_oid) + hlen != ctx->len) { - return -1; - } - - if (memcmp(p, sha256_oid, sizeof(sha256_oid))) { - return -1; - } - p += sizeof(sha256_oid); - - if (memcmp(p, hash, hlen)) { - return -1; - } - - return 0; -} - -static int -bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig, int slen, - uint8_t key_id) -{ - mbedtls_rsa_context ctx; - int rc; - uint8_t *cp; - uint8_t *end; - - mbedtls_rsa_init(&ctx, 0, 0); - - cp = (uint8_t *)bootutil_keys[key_id].key; - end = cp + *bootutil_keys[key_id].len; - - rc = bootutil_parse_rsakey(&ctx, &cp, end); - if (rc || slen != ctx.len) { - mbedtls_rsa_free(&ctx); - return rc; - } - rc = bootutil_cmp_rsasig(&ctx, hash, hlen, sig); - mbedtls_rsa_free(&ctx); - - return rc; -} -#endif - /* * Verify the integrity of the image. * Return non-zero if image could not be validated/does not validate. @@ -201,19 +83,25 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, uint32_t off; uint32_t size; uint32_t sha_off = 0; -#ifdef IMAGE_SIGNATURES - uint32_t rsa_off = 0; +#if defined(IMAGE_SIGNATURES_RSA) || defined(IMAGE_SIGNATURES_EC) + uint32_t sig_off = 0; + uint32_t sig_len = 0; #endif struct image_tlv tlv; uint8_t buf[256]; uint8_t hash[32]; int rc; -#ifdef IMAGE_SIGNATURES +#ifdef IMAGE_SIGNATURES_RSA if ((hdr->ih_flags & IMAGE_F_PKCS15_RSA2048_SHA256) == 0) { return -1; } #endif +#ifdef IMAGE_SIGNATURES_EC + if ((hdr->ih_flags & IMAGE_F_ECDSA224_SHA256) == 0) { + return -1; + } +#endif if ((hdr->ih_flags & IMAGE_F_SHA256) == 0) { return -1; } @@ -240,12 +128,22 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, } sha_off = addr + off + sizeof(tlv); } -#ifdef IMAGE_SIGNATURES +#ifdef IMAGE_SIGNATURES_RSA if (tlv.it_type == IMAGE_TLV_RSA2048) { if (tlv.it_len != 256) { /* 2048 bits */ return -1; } - rsa_off = addr + off + sizeof(tlv); + sig_off = addr + off + sizeof(tlv); + sig_len = tlv.it_len; + } +#endif +#ifdef IMAGE_SIGNATURES_EC + if (tlv.it_type == IMAGE_TLV_ECDSA224) { + if (tlv.it_len < 64) { /* oids + 2 * 28 bytes */ + return -1; + } + sig_off = addr + off + sizeof(tlv); + sig_len = tlv.it_len; } #endif } @@ -264,27 +162,25 @@ bootutil_img_validate(struct image_header *hdr, uint8_t flash_id, uint32_t addr, return -1; } } -#ifdef IMAGE_SIGNATURES - if (hdr->ih_flags & IMAGE_F_PKCS15_RSA2048_SHA256) { - if (!rsa_off) { - /* - * Header said there should be PKCS1.v5 signature, no TLV - * found. - */ - return -1; - } - rc = hal_flash_read(flash_id, rsa_off, buf, 256); - if (rc) { - return -1; - } +#if defined(IMAGE_SIGNATURES_RSA) || defined(IMAGE_SIGNATURES_EC) + if (!sig_off) { + /* + * Header said there should be PKCS1.v5 signature, no TLV + * found. + */ + return -1; + } + rc = hal_flash_read(flash_id, sig_off, buf, sig_len); + if (rc) { + return -1; + } - if (hdr->ih_key_id >= bootutil_key_cnt) { - return -1; - } - rc = bootutil_verify_sig(hash, sizeof(hash), buf, 256, hdr->ih_key_id); - if (rc) { - return -1; - } + if (hdr->ih_key_id >= bootutil_key_cnt) { + return -1; + } + rc = bootutil_verify_sig(hash, sizeof(hash), buf, sig_len, hdr->ih_key_id); + if (rc) { + return -1; } #endif return 0;