├── README.md ├── boringssl ├── LICENSE └── bssl.patch └── chromium ├── LICENSE └── chromium.patch /README.md: -------------------------------------------------------------------------------- 1 | # Channel ID Private Key Protection 2 | 3 | ## About 4 | 5 | There are two related patches in this project: The BoringSSL patch enables an 6 | opaque key for Channel ID, and the Chromium patch enables an opaque key along 7 | with providing an implementation of hardware-backed keys using the Intel SGX 8 | SDK. Together, these patches demonstrate how Chromium could store its Channel ID 9 | private keys in an Intel SGX enclave. 10 | 11 | ## Compile and run 12 | 13 | Follow the following steps to compile and run: 14 | 15 | 1. Be on a machine with an SGX processor. 16 | 2. Enter the BIOS settings, and make sure SGX is set to `enabled`. 17 | 3. Install Linux. 18 | 4. Install the SGX Alpha SDK, following the included instructions. 19 | 5. Download the chromium repository following the instructions available. We 20 | will call its path ``. 21 | 6. Checkout commit `f594a1085b49369c2479e5526dd0ef8b116e9af0` in the chromium 22 | repository. 23 | 7. `cd third_party/boringssl/src`, checkout commit 24 | `afe57cb14d36f70ad4a109fc5e7765d1adc67035`. 25 | 8. Chrome uses an included root to handle packages. 26 | ``` 27 | cd build/linux/debian_wheezy_-sysroot/ 28 | mkdir opt && cd opt && mkdir intel && cd intel 29 | cp -r /opt/intel/sgxsdk . 30 | ``` 31 | 9. Set up pkgconfig by creating the file `/usr/lib/pkgconfig/sgx.pc` with contents: 32 | 33 | ``` 34 | prefix=/opt/intel/sgxsdk 35 | exec_prefix=${prefix} 36 | includedir=${prefix}/include 37 | libdir=${prefix}/lib64 38 | 39 | Name: sgx 40 | Description: Intel SGX SDK for Linux 41 | Version: 1.0.0 42 | Cflags: -I${includedir} 43 | Libs: -L${libdir} -lsgx_urts -lsgx_uae_service -lsgx_tservice 44 | ``` 45 | 10. add to `~/.bashrc`: 46 | ``` 47 | export LD_LIBRARY_PATH=/lib64:/usr/lib:/opt/intel/sgxsdk/lib64 48 | export CHROME_DEVEL_SANDBOX="/usr/local/sbin/chrome-devel-sandbox" 49 | ``` 50 | (this second one should already be there if chrome compiles properly) 51 | 11. Apply `chromium/chromium.patch` to `/src`. 52 | 12. Apply `boringssl/bssl.patch` to `third_party/boringssl/src`. 53 | 13. If you're using gn, from `/src`: 54 | ``` 55 | gn args out/Default 56 | add the line: 57 | enable_nacl = false 58 | ``` 59 | 14. Compile the enclave 60 | ``` 61 | cd net/ssl 62 | make 63 | cd ../../ 64 | ``` 65 | 15. Compile chrome 66 | (first time: `ninja -C out/Default chrome chrome_sandbox`) 67 | ``` 68 | ninja -C out/Default chrome 69 | ``` 70 | 16. Run chrome 71 | ``` 72 | out/Default/chrome 73 | ``` 74 | 17. Load google.com 75 | 76 | If you want to run tests: 77 | ``` 78 | ninja -C out/Default net_unittests 79 | out/Default/net_unittests --gtest_filter=*ChannelID* 80 | ``` 81 | 82 | There are more tests within boringssl, with instructions in 83 | `third_party/boringssl/src/BUILDING.md` 84 | -------------------------------------------------------------------------------- /boringssl/LICENSE: -------------------------------------------------------------------------------- 1 | BoringSSL is a fork of OpenSSL. As such, large parts of it fall under OpenSSL 2 | licensing. Files that are completely new have a Google copyright and an ISC 3 | license. This license is reproduced at the bottom of this file. 4 | 5 | Contributors to BoringSSL are required to follow the CLA rules for Chromium: 6 | https://cla.developers.google.com/clas 7 | 8 | Some files from Intel are under yet another license, which is also included 9 | underneath. 10 | 11 | The OpenSSL toolkit stays under a dual license, i.e. both the conditions of the 12 | OpenSSL License and the original SSLeay license apply to the toolkit. See below 13 | for the actual license texts. Actually both licenses are BSD-style Open Source 14 | licenses. In case of any license issues related to OpenSSL please contact 15 | openssl-core@openssl.org. 16 | 17 | OpenSSL License 18 | --------------- 19 | 20 | /* ==================================================================== 21 | * Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved. 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions 25 | * are met: 26 | * 27 | * 1. Redistributions of source code must retain the above copyright 28 | * notice, this list of conditions and the following disclaimer. 29 | * 30 | * 2. Redistributions in binary form must reproduce the above copyright 31 | * notice, this list of conditions and the following disclaimer in 32 | * the documentation and/or other materials provided with the 33 | * distribution. 34 | * 35 | * 3. All advertising materials mentioning features or use of this 36 | * software must display the following acknowledgment: 37 | * "This product includes software developed by the OpenSSL Project 38 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 39 | * 40 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 41 | * endorse or promote products derived from this software without 42 | * prior written permission. For written permission, please contact 43 | * openssl-core@openssl.org. 44 | * 45 | * 5. Products derived from this software may not be called "OpenSSL" 46 | * nor may "OpenSSL" appear in their names without prior written 47 | * permission of the OpenSSL Project. 48 | * 49 | * 6. Redistributions of any form whatsoever must retain the following 50 | * acknowledgment: 51 | * "This product includes software developed by the OpenSSL Project 52 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 55 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 57 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 58 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 60 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 61 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 63 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 64 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 65 | * OF THE POSSIBILITY OF SUCH DAMAGE. 66 | * ==================================================================== 67 | * 68 | * This product includes cryptographic software written by Eric Young 69 | * (eay@cryptsoft.com). This product includes software written by Tim 70 | * Hudson (tjh@cryptsoft.com). 71 | * 72 | */ 73 | 74 | Original SSLeay License 75 | ----------------------- 76 | 77 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 78 | * All rights reserved. 79 | * 80 | * This package is an SSL implementation written 81 | * by Eric Young (eay@cryptsoft.com). 82 | * The implementation was written so as to conform with Netscapes SSL. 83 | * 84 | * This library is free for commercial and non-commercial use as long as 85 | * the following conditions are aheared to. The following conditions 86 | * apply to all code found in this distribution, be it the RC4, RSA, 87 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 88 | * included with this distribution is covered by the same copyright terms 89 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 90 | * 91 | * Copyright remains Eric Young's, and as such any Copyright notices in 92 | * the code are not to be removed. 93 | * If this package is used in a product, Eric Young should be given attribution 94 | * as the author of the parts of the library used. 95 | * This can be in the form of a textual message at program startup or 96 | * in documentation (online or textual) provided with the package. 97 | * 98 | * Redistribution and use in source and binary forms, with or without 99 | * modification, are permitted provided that the following conditions 100 | * are met: 101 | * 1. Redistributions of source code must retain the copyright 102 | * notice, this list of conditions and the following disclaimer. 103 | * 2. Redistributions in binary form must reproduce the above copyright 104 | * notice, this list of conditions and the following disclaimer in the 105 | * documentation and/or other materials provided with the distribution. 106 | * 3. All advertising materials mentioning features or use of this software 107 | * must display the following acknowledgement: 108 | * "This product includes cryptographic software written by 109 | * Eric Young (eay@cryptsoft.com)" 110 | * The word 'cryptographic' can be left out if the rouines from the library 111 | * being used are not cryptographic related :-). 112 | * 4. If you include any Windows specific code (or a derivative thereof) from 113 | * the apps directory (application code) you must include an acknowledgement: 114 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 115 | * 116 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 117 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 118 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 119 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 120 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 121 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 122 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 123 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 124 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 125 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 126 | * SUCH DAMAGE. 127 | * 128 | * The licence and distribution terms for any publically available version or 129 | * derivative of this code cannot be changed. i.e. this code cannot simply be 130 | * copied and put under another distribution licence 131 | * [including the GNU Public Licence.] 132 | */ 133 | 134 | 135 | ISC license used for completely new code in BoringSSL: 136 | 137 | /* Copyright (c) 2015, Google Inc. 138 | * 139 | * Permission to use, copy, modify, and/or distribute this software for any 140 | * purpose with or without fee is hereby granted, provided that the above 141 | * copyright notice and this permission notice appear in all copies. 142 | * 143 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 144 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 145 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 146 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 147 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 148 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 149 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 150 | 151 | 152 | Some files from Intel carry the following license: 153 | 154 | # Copyright (c) 2012, Intel Corporation 155 | # 156 | # All rights reserved. 157 | # 158 | # Redistribution and use in source and binary forms, with or without 159 | # modification, are permitted provided that the following conditions are 160 | # met: 161 | # 162 | # * Redistributions of source code must retain the above copyright 163 | # notice, this list of conditions and the following disclaimer. 164 | # 165 | # * Redistributions in binary form must reproduce the above copyright 166 | # notice, this list of conditions and the following disclaimer in the 167 | # documentation and/or other materials provided with the 168 | # distribution. 169 | # 170 | # * Neither the name of the Intel Corporation nor the names of its 171 | # contributors may be used to endorse or promote products derived from 172 | # this software without specific prior written permission. 173 | # 174 | # 175 | # THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY 176 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 177 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178 | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR 179 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 180 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 181 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 182 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 183 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 184 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 185 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 186 | -------------------------------------------------------------------------------- /boringssl/bssl.patch: -------------------------------------------------------------------------------- 1 | From 9d63fd305f4c220cc8ffd1ac3aa3aa787008ac56 Mon Sep 17 00:00:00 2001 2 | From: Erica Portnoy 3 | Date: Tue, 29 Mar 2016 12:42:55 -0700 4 | Subject: [PATCH] Support SGX Channel ID private key PoC, based on 5 | afe57cb14d36f70ad4a109fc5e7765d1adc67035 6 | 7 | --- 8 | crypto/ecdsa/ecdsa_asn1.c | 19 +++++++++++++++ 9 | include/openssl/bio.h | 4 +++ 10 | include/openssl/ecdsa.h | 4 +++ 11 | include/openssl/ssl.h | 59 ++++++++++++++++++++++++++++++++++++++++++++ 12 | ssl/internal.h | 6 +++++ 13 | ssl/s3_clnt.c | 38 +++++++++++++++++++++++++++++ 14 | ssl/s3_lib.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 15 | ssl/ssl_lib.c | 39 +++++++++++++++++++++++++++++ 16 | ssl/t1_lib.c | 48 ++++++++++++++++++++++++++++++++++++ 17 | 9 files changed, 279 insertions(+) 18 | 19 | diff --git a/crypto/ecdsa/ecdsa_asn1.c b/crypto/ecdsa/ecdsa_asn1.c 20 | index 3fee191..404b185 100644 21 | --- a/crypto/ecdsa/ecdsa_asn1.c 22 | +++ b/crypto/ecdsa/ecdsa_asn1.c 23 | @@ -108,6 +108,25 @@ void ECDSA_SIG_free(ECDSA_SIG *sig) { 24 | OPENSSL_free(sig); 25 | } 26 | 27 | +ECDSA_SIG *ECDSA_SIG_copy(ECDSA_SIG *signature) { 28 | + if (signature == NULL) { 29 | + return NULL; 30 | + } 31 | + ECDSA_SIG *sig = ECDSA_SIG_new(); 32 | + if (sig == NULL) { 33 | + return NULL; 34 | + } 35 | + if (!BN_copy(sig->r, signature->r)) { 36 | + ECDSA_SIG_free(sig); 37 | + return NULL; 38 | + } 39 | + if (!BN_copy(sig->s, signature->s)) { 40 | + ECDSA_SIG_free(sig); 41 | + return NULL; 42 | + } 43 | + return sig; 44 | +} 45 | + 46 | ECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) { 47 | ECDSA_SIG *ret = ECDSA_SIG_new(); 48 | if (ret == NULL) { 49 | diff --git a/include/openssl/bio.h b/include/openssl/bio.h 50 | index c88a3e1..55f1d2c 100644 51 | --- a/include/openssl/bio.h 52 | +++ b/include/openssl/bio.h 53 | @@ -194,6 +194,10 @@ OPENSSL_EXPORT int BIO_should_io_special(const BIO *bio); 54 | * a private key for a TLS connection. */ 55 | #define BIO_RR_SSL_CHANNEL_ID_LOOKUP 0x04 56 | 57 | +/* BIO_RR_SSL_CHANNEL_ID_SIGNATURE indicates that the ChannelID code cannot find 58 | + * the digest for a TLS connection. */ 59 | +#define BIO_RR_SSL_CHANNEL_ID_SIGNATURE 0x05 60 | + 61 | /* BIO_get_retry_reason returns the special I/O operation that needs to be 62 | * retried. The return value is one of the |BIO_RR_*| values. */ 63 | OPENSSL_EXPORT int BIO_get_retry_reason(const BIO *bio); 64 | diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h 65 | index f3f68eb..717c21a 100644 66 | --- a/include/openssl/ecdsa.h 67 | +++ b/include/openssl/ecdsa.h 68 | @@ -106,6 +106,10 @@ OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_new(void); 69 | /* ECDSA_SIG_free frees |sig| its member |BIGNUM|s. */ 70 | OPENSSL_EXPORT void ECDSA_SIG_free(ECDSA_SIG *sig); 71 | 72 | +/* ECDSA_SIG_copy returns a fresh |ECDSA_SIG| initialized to the contents of 73 | + |signature| or NULL on error. */ 74 | +OPENSSL_EXPORT ECDSA_SIG *ECDSA_SIG_copy(ECDSA_SIG *signature); 75 | + 76 | /* ECDSA_do_sign signs |digest_len| bytes from |digest| with |key| and returns 77 | * the resulting signature structure, or NULL on error. */ 78 | OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, 79 | diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h 80 | index bce981c..9844f24 100644 81 | --- a/include/openssl/ssl.h 82 | +++ b/include/openssl/ssl.h 83 | @@ -468,6 +468,11 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code); 84 | * See also |SSL_set_private_key_method|. */ 85 | #define SSL_ERROR_WANT_PRIVATE_KEY_OPERATION 13 86 | 87 | + /* SSL_ERROR_WANT_CHANNEL_ID_SIGNATURE indicates the operation failed looking 88 | + * up the Channel ID signature. The caller may retry the operation when one 89 | + * has been configured with |SSL_set1_tls_channel_id_signature|. */ 90 | +#define SSL_ERROR_WANT_CHANNEL_ID_SIGNATURE 14 91 | + 92 | /* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success 93 | * and zero on failure. */ 94 | OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu); 95 | @@ -2337,6 +2342,28 @@ OPENSSL_EXPORT int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key); 96 | OPENSSL_EXPORT size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, 97 | size_t max_out); 98 | 99 | +/* SSL_get_tls_channel_id_digest copies the digest that the channel ID will 100 | + * be used to sign. It returns one on success and zero on error. */ 101 | +OPENSSL_EXPORT int SSL_get_tls_channel_id_digest(SSL *ssl, uint8_t *out); 102 | + 103 | +/* SSL_set1_tls_channel_id_signature configures a TLS client to send a TLS Channel ID to 104 | + * compatible servers. It returns one on success and zero on error. */ 105 | +OPENSSL_EXPORT int SSL_set1_tls_channel_id_signature(SSL *ssl, ECDSA_SIG *signature); 106 | + 107 | +/* SSL_set1_tls_channel_id_public_key configures a TLS client to send a TLS Channel ID to 108 | + * compatible servers. It returns one on success and zero on error. */ 109 | +OPENSSL_EXPORT int SSL_set1_tls_channel_id_public_key(SSL *ssl, EVP_PKEY *public_key); 110 | + 111 | +/* SSL_CTX_set1_tls_channel_id_signature configures a TLS client to send a TLS Channel ID 112 | + * to compatible servers. It returns one on success and zero on error. */ 113 | +OPENSSL_EXPORT int SSL_CTX_set1_tls_channel_id_signature(SSL_CTX *ctx, 114 | + ECDSA_SIG *signature); 115 | + 116 | +/* SSL_set1_tls_channel_id_digest configures a TLS client to send a TLS Channel ID to 117 | + * compatible servers. It returns one on success and zero on error. */ 118 | +OPENSSL_EXPORT int SSL_set1_tls_channel_id_digest(SSL *ssl, uint8_t *digest, 119 | + size_t digest_len); 120 | + 121 | /* SSL_CTX_set_channel_id_cb sets a callback to be called when a TLS Channel ID 122 | * is requested. The callback may set |*out_pkey| to a key, passing a reference 123 | * to the caller. If none is returned, the handshake will pause and 124 | @@ -3188,6 +3215,7 @@ OPENSSL_EXPORT int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))( 125 | #define SSL_PENDING_SESSION 7 126 | #define SSL_CERTIFICATE_SELECTION_PENDING 8 127 | #define SSL_PRIVATE_KEY_OPERATION 9 128 | +#define SSL_CHANNEL_ID_SIGNATURE 10 129 | 130 | /* SSL_want returns one of the above values to determine what the most recent 131 | * operation on |ssl| was blocked on. Use |SSL_get_error| instead. */ 132 | @@ -3198,6 +3226,8 @@ OPENSSL_EXPORT int SSL_want(const SSL *ssl); 133 | #define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING) 134 | #define SSL_want_x509_lookup(ssl) (SSL_want(ssl) == SSL_X509_LOOKUP) 135 | #define SSL_want_channel_id_lookup(ssl) (SSL_want(ssl) == SSL_CHANNEL_ID_LOOKUP) 136 | +#define SSL_want_channel_id_signature(ssl) \ 137 | + (SSL_want(ssl) == SSL_CHANNEL_ID_SIGNATURE) 138 | #define SSL_want_session(ssl) (SSL_want(ssl) == SSL_PENDING_SESSION) 139 | #define SSL_want_certificate(ssl) \ 140 | (SSL_want(ssl) == SSL_CERTIFICATE_SELECTION_PENDING) 141 | @@ -3666,6 +3696,18 @@ struct ssl_ctx_st { 142 | /* The client's Channel ID private key. */ 143 | EVP_PKEY *tlsext_channel_id_private; 144 | 145 | + /* The client's signature over the Channel ID digest. */ 146 | + ECDSA_SIG *tlsext_channel_id_signature; 147 | + 148 | + /* The client's Channel ID public key. */ 149 | + EVP_PKEY *tlsext_channel_id_public_key; 150 | + 151 | + /* The digest for the client to sign using the Channel ID private key. */ 152 | + uint8_t *tlsext_channel_id_digest; 153 | + 154 | + /* The length of |tlsext_channel_id_digest|. */ 155 | + size_t tlsext_channel_id_digest_len; 156 | + 157 | /* Signed certificate timestamp list to be sent to the client, if requested */ 158 | uint8_t *signed_cert_timestamp_list; 159 | size_t signed_cert_timestamp_list_length; 160 | @@ -3847,6 +3889,18 @@ struct ssl_st { 161 | /* The client's Channel ID private key. */ 162 | EVP_PKEY *tlsext_channel_id_private; 163 | 164 | + /* The client's signature over the Channel ID digest. */ 165 | + ECDSA_SIG *tlsext_channel_id_signature; 166 | + 167 | + /* The client's Channel ID public key. */ 168 | + EVP_PKEY *tlsext_channel_id_public_key; 169 | + 170 | + /* The digest for the client to sign using the Channel ID private key. */ 171 | + uint8_t *tlsext_channel_id_digest; 172 | + 173 | + /* The length of |tlsext_channel_id_digest|. */ 174 | + size_t tlsext_channel_id_digest_len; 175 | + 176 | /* For a client, this contains the list of supported protocols in wire 177 | * format. */ 178 | uint8_t *alpn_client_proto_list; 179 | @@ -4229,6 +4283,7 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); 180 | #define SSL_CTX_set1_chain SSL_CTX_set1_chain 181 | #define SSL_CTX_set1_curves SSL_CTX_set1_curves 182 | #define SSL_CTX_set1_tls_channel_id SSL_CTX_set1_tls_channel_id 183 | +#define SSL_CTX_set1_tls_channel_id_signature SSL_CTX_set1_tls_channel_id_signature 184 | #define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list 185 | #define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment 186 | #define SSL_CTX_set_mode SSL_CTX_set_mode 187 | @@ -4265,6 +4320,10 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); 188 | #define SSL_set1_chain SSL_set1_chain 189 | #define SSL_set1_curves SSL_set1_curves 190 | #define SSL_set1_tls_channel_id SSL_set1_tls_channel_id 191 | +#define SSL_set1_tls_channel_id_signature SSL_set1_tls_channel_id_signature 192 | +#define SSL_set1_tls_channel_id_public_key SSL_set1_tls_channel_id_public_key 193 | +#define SSL_get_tls_channel_id_digest SSL_get_tls_channel_id_digest 194 | +#define SSL_set1_tls_channel_id_digest SSL_set1_tls_channel_id_digest 195 | #define SSL_set_max_cert_list SSL_set_max_cert_list 196 | #define SSL_set_max_send_fragment SSL_set_max_send_fragment 197 | #define SSL_set_mode SSL_set_mode 198 | diff --git a/ssl/internal.h b/ssl/internal.h 199 | index bbbd939..3434052 100644 200 | --- a/ssl/internal.h 201 | +++ b/ssl/internal.h 202 | @@ -1202,6 +1202,12 @@ const EVP_MD *tls12_get_hash(uint8_t hash_alg); 203 | * one on success and zero on failure. */ 204 | int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len); 205 | 206 | +/* tls1_channel_id_concat concatenates the values that will be hashed and signed by 207 | + * Channel ID and writes them to an allocated buffer that it places in |out|. 208 | + * The caller is responsible for calling |free| on |out|. It returns one on 209 | + * success and zero on failure. */ 210 | +int tls1_channel_id_concat(SSL *ssl, uint8_t **out, size_t *out_len); 211 | + 212 | int tls1_record_handshake_hashes_for_channel_id(SSL *s); 213 | 214 | /* ssl_log_rsa_client_key_exchange logs |premaster|, if logging is enabled for 215 | diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c 216 | index f9d7693..a96e010 100644 217 | --- a/ssl/s3_clnt.c 218 | +++ b/ssl/s3_clnt.c 219 | @@ -171,6 +171,8 @@ 220 | #include "internal.h" 221 | #include "../crypto/dh/internal.h" 222 | 223 | +// Define SGX_ENABLE for sealing private keys in SGX 224 | +#define SGX_ENABLE 225 | 226 | int ssl3_connect(SSL *s) { 227 | BUF_MEM *buf = NULL; 228 | @@ -2145,6 +2147,41 @@ int ssl3_send_channel_id(SSL *ssl) { 229 | 230 | assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A); 231 | 232 | +#ifdef SGX_ENABLE 233 | + if (ssl->tlsext_channel_id_signature == NULL) { 234 | + uint8_t *digest; 235 | + size_t digest_len; 236 | + if (!tls1_channel_id_concat(ssl, &digest, &digest_len)) { 237 | + return -1; 238 | + } 239 | + // this is not the digest, 240 | + // but rather the concatenated items that will be digested by 241 | + // the sgx ecdsa sign method. 242 | + if (!SSL_set1_tls_channel_id_digest(ssl, digest, digest_len)) { 243 | + return -1; 244 | + } 245 | + ssl->rwstate = SSL_CHANNEL_ID_SIGNATURE; 246 | + free(digest); 247 | + return -1; 248 | + } 249 | + ssl->rwstate = SSL_NOTHING; 250 | + // if the signature is set, the public key should be set as well 251 | + ECDSA_SIG *sig = ECDSA_SIG_copy(ssl->tlsext_channel_id_signature); 252 | + // |err| frees |x| and |y| and returns |ret| 253 | + BIGNUM *x = BN_new(); 254 | + BIGNUM *y = BN_new(); 255 | + int ret = -1; 256 | + if (!sig) { 257 | + goto err; 258 | + } 259 | + EC_KEY *ec_key = ssl->tlsext_channel_id_public_key->pkey.ec; 260 | + if (x == NULL || y == NULL || 261 | + !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), 262 | + EC_KEY_get0_public_key(ec_key), 263 | + x, y, NULL)) { 264 | + goto err; 265 | + } 266 | +#else 267 | if (ssl->tlsext_channel_id_private == NULL && 268 | ssl->ctx->channel_id_cb != NULL) { 269 | EVP_PKEY *key = NULL; 270 | @@ -2190,6 +2227,7 @@ int ssl3_send_channel_id(SSL *ssl) { 271 | if (sig == NULL) { 272 | goto err; 273 | } 274 | +#endif 275 | 276 | CBB cbb, child; 277 | size_t length; 278 | diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c 279 | index 3f8cea0..855263e 100644 280 | --- a/ssl/s3_lib.c 281 | +++ b/ssl/s3_lib.c 282 | @@ -358,6 +358,68 @@ size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) { 283 | return 64; 284 | } 285 | 286 | +int SSL_get_tls_channel_id_digest(SSL *ssl, uint8_t *out) { 287 | + memcpy(out, ssl->tlsext_channel_id_digest, 288 | + ssl->tlsext_channel_id_digest_len); 289 | + return 1; 290 | +} 291 | + 292 | +int SSL_CTX_set1_tls_channel_id_signature(SSL_CTX *ctx, ECDSA_SIG *signature) { 293 | + if (signature == NULL) { 294 | + return 0; 295 | + } 296 | + ctx->tlsext_channel_id_enabled = 1; 297 | + ECDSA_SIG_free(ctx->tlsext_channel_id_signature); 298 | + ECDSA_SIG *sig = ECDSA_SIG_copy(signature); 299 | + if (sig == NULL) { 300 | + return 0; 301 | + } 302 | + ctx->tlsext_channel_id_signature = sig; 303 | + return 1; 304 | +} 305 | + 306 | +int SSL_set1_tls_channel_id_signature(SSL *ssl, ECDSA_SIG *signature) { 307 | + if (signature == NULL) { 308 | + return 0; 309 | + } 310 | + ssl->tlsext_channel_id_enabled = 1; 311 | + ECDSA_SIG_free(ssl->tlsext_channel_id_signature); 312 | + ECDSA_SIG *sig = ECDSA_SIG_copy(signature); 313 | + if (sig == NULL) { 314 | + return 0; 315 | + } 316 | + ssl->tlsext_channel_id_signature = sig; 317 | + return 1; 318 | +} 319 | + 320 | +int SSL_set1_tls_channel_id_public_key(SSL *ssl, EVP_PKEY *public_key) { 321 | + if (public_key == NULL) { 322 | + return 0; 323 | + } 324 | + ssl->tlsext_channel_id_enabled = 1; 325 | + EVP_PKEY_free(ssl->tlsext_channel_id_public_key); 326 | + ssl->tlsext_channel_id_public_key = EVP_PKEY_up_ref(public_key); 327 | + return 1; 328 | +} 329 | + 330 | +int SSL_set1_tls_channel_id_digest(SSL *ssl, uint8_t *digest, size_t digest_len) { 331 | + if (digest == NULL) { 332 | + return 0; 333 | + } 334 | + ssl->tlsext_channel_id_enabled = 1; 335 | + if (ssl->tlsext_channel_id_digest != NULL) { 336 | + free(ssl->tlsext_channel_id_digest); 337 | + } 338 | + uint8_t *dig = calloc(digest_len, sizeof(uint8_t)); 339 | + if (dig == NULL) { 340 | + return 0; 341 | + } 342 | + memcpy(dig, digest, digest_len); 343 | + ssl->tlsext_channel_id_digest = dig; 344 | + ssl->tlsext_channel_id_digest_len = digest_len; 345 | + return 1; 346 | +} 347 | + 348 | int SSL_set_tlsext_host_name(SSL *ssl, const char *name) { 349 | OPENSSL_free(ssl->tlsext_hostname); 350 | ssl->tlsext_hostname = NULL; 351 | diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c 352 | index beb57ad..1d81062 100644 353 | --- a/ssl/ssl_lib.c 354 | +++ b/ssl/ssl_lib.c 355 | @@ -339,6 +339,11 @@ void SSL_CTX_free(SSL_CTX *ctx) { 356 | OPENSSL_free(ctx->ocsp_response); 357 | OPENSSL_free(ctx->signed_cert_timestamp_list); 358 | EVP_PKEY_free(ctx->tlsext_channel_id_private); 359 | + ECDSA_SIG_free(ctx->tlsext_channel_id_signature); 360 | + EVP_PKEY_free(ctx->tlsext_channel_id_public_key); 361 | + if (ctx->tlsext_channel_id_digest != NULL) { 362 | + free(ctx->tlsext_channel_id_digest); 363 | + } 364 | 365 | OPENSSL_free(ctx); 366 | } 367 | @@ -442,6 +447,31 @@ SSL *SSL_new(SSL_CTX *ctx) { 368 | EVP_PKEY_up_ref(ctx->tlsext_channel_id_private); 369 | } 370 | 371 | + if (ctx->tlsext_channel_id_signature) { 372 | + ECDSA_SIG *sig = ECDSA_SIG_copy(ctx->tlsext_channel_id_signature); 373 | + if (sig == NULL) { 374 | + goto err; 375 | + } 376 | + s->tlsext_channel_id_signature = sig; 377 | + } 378 | + if (ctx->tlsext_channel_id_public_key) { 379 | + EVP_PKEY *key = EVP_PKEY_new(); 380 | + if (key == NULL) { 381 | + goto err; 382 | + } 383 | + EVP_PKEY_copy_parameters(key, ctx->tlsext_channel_id_public_key); 384 | + s->tlsext_channel_id_public_key = key; 385 | + } 386 | + if (ctx->tlsext_channel_id_digest) { 387 | + uint8_t *dig = calloc(ctx->tlsext_channel_id_digest_len, sizeof(uint8_t)); 388 | + if (dig == NULL) { 389 | + goto err; 390 | + } 391 | + memcpy(dig, ctx->tlsext_channel_id_digest, ctx->tlsext_channel_id_digest_len); 392 | + s->tlsext_channel_id_digest = dig; 393 | + s->tlsext_channel_id_digest_len = ctx->tlsext_channel_id_digest_len; 394 | + } 395 | + 396 | s->signed_cert_timestamps_enabled = s->ctx->signed_cert_timestamps_enabled; 397 | s->ocsp_stapling_enabled = s->ctx->ocsp_stapling_enabled; 398 | 399 | @@ -496,6 +526,11 @@ void SSL_free(SSL *ssl) { 400 | OPENSSL_free(ssl->tlsext_ellipticcurvelist); 401 | OPENSSL_free(ssl->alpn_client_proto_list); 402 | EVP_PKEY_free(ssl->tlsext_channel_id_private); 403 | + ECDSA_SIG_free(ssl->tlsext_channel_id_signature); 404 | + EVP_PKEY_free(ssl->tlsext_channel_id_public_key); 405 | + if (ssl->tlsext_channel_id_digest != NULL) { 406 | + free(ssl->tlsext_channel_id_digest); 407 | + } 408 | OPENSSL_free(ssl->psk_identity_hint); 409 | sk_X509_NAME_pop_free(ssl->client_CA, X509_NAME_free); 410 | OPENSSL_free(ssl->next_proto_negotiated); 411 | @@ -793,6 +828,10 @@ int SSL_get_error(const SSL *ssl, int ret_code) { 412 | return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP; 413 | } 414 | 415 | + if (SSL_want_channel_id_signature(ssl)) { 416 | + return SSL_ERROR_WANT_CHANNEL_ID_SIGNATURE; 417 | + } 418 | + 419 | if (SSL_want_private_key_operation(ssl)) { 420 | return SSL_ERROR_WANT_PRIVATE_KEY_OPERATION; 421 | } 422 | diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c 423 | index c0ef97e..1112f0b 100644 424 | --- a/ssl/t1_lib.c 425 | +++ b/ssl/t1_lib.c 426 | @@ -2881,6 +2881,54 @@ err: 427 | return ret; 428 | } 429 | 430 | +// caller must free |out| 431 | +int tls1_channel_id_concat(SSL *ssl, uint8_t **out, size_t *out_len) { 432 | + int ret = 0; 433 | + // calculate total_length of output 434 | + static const char kClientIDMagic[] = "TLS Channel ID signature"; 435 | + size_t total_length = sizeof(kClientIDMagic); 436 | + static const char kResumptionMagic[] = "Resumption"; 437 | + if (ssl->hit) { 438 | + total_length += sizeof(kResumptionMagic); 439 | + if (ssl->session->original_handshake_hash_len == 0) { 440 | + OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); 441 | + goto err; 442 | + } 443 | + total_length += ssl->session->original_handshake_hash_len; 444 | + } 445 | + uint8_t handshake_hash[EVP_MAX_MD_SIZE]; 446 | + int handshake_hash_len = tls1_handshake_digest(ssl, handshake_hash, 447 | + sizeof(handshake_hash)); 448 | + if (handshake_hash_len < 0) { 449 | + goto err; 450 | + } 451 | + total_length += (size_t)handshake_hash_len; 452 | + // allocate total_length memory 453 | + uint8_t *output = malloc(total_length); 454 | + if (!output) { 455 | + goto err; 456 | + } 457 | + *out_len = sizeof(kClientIDMagic); 458 | + memcpy(output, kClientIDMagic, *out_len); 459 | + if (ssl->hit) { 460 | + memcpy(&output[*out_len], kResumptionMagic, sizeof(kResumptionMagic)); 461 | + *out_len += sizeof(kResumptionMagic); 462 | + memcpy(&output[*out_len], ssl->session->original_handshake_hash, 463 | + ssl->session->original_handshake_hash_len); 464 | + *out_len += ssl->session->original_handshake_hash_len; 465 | + } 466 | + memcpy(&output[*out_len], handshake_hash, (size_t)handshake_hash_len); 467 | + *out_len += (size_t)handshake_hash_len; 468 | + if (*out_len != total_length) { 469 | + free(output); 470 | + goto err; 471 | + } 472 | + *out = output; 473 | + ret = 1; 474 | +err: 475 | + return ret; 476 | +} 477 | + 478 | /* tls1_record_handshake_hashes_for_channel_id records the current handshake 479 | * hashes in |s->session| so that Channel ID resumptions can sign that data. */ 480 | int tls1_record_handshake_hashes_for_channel_id(SSL *s) { 481 | -- 482 | 2.8.0.rc3.226.g39d4020 483 | 484 | -------------------------------------------------------------------------------- /chromium/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Chromium Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /chromium/chromium.patch: -------------------------------------------------------------------------------- 1 | From aaa3db2efb07f13a1735c78fea90c13ca609796e Mon Sep 17 00:00:00 2001 2 | From: Erica Portnoy 3 | Date: Tue, 29 Mar 2016 13:19:41 -0700 4 | Subject: [PATCH] Functioning SGX Private Key PoC based on 5 | f594a1085b49369c2479e5526dd0ef8b116e9af0 6 | 7 | --- 8 | build/config/linux/BUILD.gn | 4 + 9 | crypto/ec_private_key.h | 16 +- 10 | crypto/ec_private_key_openssl.cc | 98 ++++++++++- 11 | net/BUILD.gn | 11 +- 12 | net/base/net_error_list.h | 3 + 13 | net/log/net_log_event_type_list.h | 6 + 14 | net/net.gypi | 4 + 15 | net/socket/ssl_client_socket_openssl.cc | 97 +++++++++++ 16 | net/socket/ssl_client_socket_openssl.h | 4 + 17 | net/ssl/Makefile | 92 +++++++++++ 18 | .../channel_id_enclave/channel_id_key_manager.c | 101 ++++++++++++ 19 | .../channel_id_key_manager.config.xml | 11 ++ 20 | .../channel_id_enclave/channel_id_key_manager.edl | 22 +++ 21 | .../channel_id_enclave/channel_id_key_manager.lds | 13 ++ 22 | .../channel_id_key_manager_private.pem | 39 +++++ 23 | net/ssl/channel_id_service.cc | 181 ++++++++++++++++++++- 24 | net/ssl/channel_id_service.h | 27 ++- 25 | net/ssl/channel_id_service_unittest.cc | 36 ++++ 26 | net/ssl/sgx_util.cc | 83 ++++++++++ 27 | net/ssl/sgx_util.h | 30 ++++ 28 | tools/metrics/histograms/histograms.xml | 7 + 29 | 21 files changed, 877 insertions(+), 8 deletions(-) 30 | create mode 100644 net/ssl/Makefile 31 | create mode 100644 net/ssl/channel_id_enclave/channel_id_key_manager.c 32 | create mode 100644 net/ssl/channel_id_enclave/channel_id_key_manager.config.xml 33 | create mode 100644 net/ssl/channel_id_enclave/channel_id_key_manager.edl 34 | create mode 100644 net/ssl/channel_id_enclave/channel_id_key_manager.lds 35 | create mode 100644 net/ssl/channel_id_enclave/channel_id_key_manager_private.pem 36 | create mode 100644 net/ssl/sgx_util.cc 37 | create mode 100644 net/ssl/sgx_util.h 38 | 39 | diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn 40 | index a19b8f1..577b398 100644 41 | --- a/build/config/linux/BUILD.gn 42 | +++ b/build/config/linux/BUILD.gn 43 | @@ -37,6 +37,10 @@ pkg_config("freetype2") { 44 | packages = [ "freetype2" ] 45 | } 46 | 47 | +pkg_config("sgx") { 48 | + packages = [ "sgx" ] 49 | +} 50 | + 51 | pkg_config("glib") { 52 | packages = [ 53 | "glib-2.0", 54 | diff --git a/crypto/ec_private_key.h b/crypto/ec_private_key.h 55 | index 9a8a02a..b7d6daf 100644 56 | --- a/crypto/ec_private_key.h 57 | +++ b/crypto/ec_private_key.h 58 | @@ -8,6 +8,8 @@ 59 | #include 60 | #include 61 | 62 | +#include 63 | +#include 64 | #include 65 | #include 66 | 67 | @@ -46,7 +48,7 @@ class CRYPTO_EXPORT ECPrivateKey { 68 | // The key pair is given as an ASN.1-encoded PKCS #8 EncryptedPrivateKeyInfo 69 | // block and an X.509 SubjectPublicKeyInfo block. 70 | // Returns NULL if initialization fails. 71 | - static ECPrivateKey* CreateFromEncryptedPrivateKeyInfo( 72 | + static ECPrivateKey* CreateFromEncryptedPrivateKeyInfo( 73 | const std::string& password, 74 | const std::vector& encrypted_private_key_info, 75 | const std::vector& subject_public_key_info); 76 | @@ -66,6 +68,12 @@ class CRYPTO_EXPORT ECPrivateKey { 77 | bool sensitive, 78 | SECKEYPrivateKey** key, 79 | SECKEYPublicKey** public_key); 80 | +#else 81 | + // Makes a private copy of the public key 82 | + static ECPrivateKey* CreateFromKeyBlobAndPublicKey( 83 | + uint8_t *sealed_key, 84 | + uint32_t sealed_key_size, 85 | + EC_KEY *public_key); 86 | #endif 87 | 88 | // Returns a copy of the object. 89 | @@ -73,6 +81,9 @@ class CRYPTO_EXPORT ECPrivateKey { 90 | 91 | #if defined(USE_OPENSSL) 92 | EVP_PKEY* key() { return key_; } 93 | + uint8_t *key_blob() { return key_blob_; } 94 | + uint32_t key_blob_size() {return key_blob_size_; } 95 | + EVP_PKEY* public_key() { return public_key_; } 96 | #else 97 | SECKEYPrivateKey* key() { return key_; } 98 | SECKEYPublicKey* public_key() { return public_key_; } 99 | @@ -104,6 +115,9 @@ class CRYPTO_EXPORT ECPrivateKey { 100 | 101 | #if defined(USE_OPENSSL) 102 | EVP_PKEY* key_; 103 | + uint8_t* key_blob_; 104 | + uint32_t key_blob_size_; 105 | + EVP_PKEY* public_key_; 106 | #else 107 | SECKEYPrivateKey* key_; 108 | SECKEYPublicKey* public_key_; 109 | diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc 110 | index d896203..07fe8cc 100644 111 | --- a/crypto/ec_private_key_openssl.cc 112 | +++ b/crypto/ec_private_key_openssl.cc 113 | @@ -4,18 +4,23 @@ 114 | 115 | #include "crypto/ec_private_key.h" 116 | 117 | +#include 118 | + 119 | #include 120 | #include 121 | #include 122 | #include 123 | #include 124 | #include 125 | +#include 126 | 127 | #include "base/logging.h" 128 | #include "base/memory/scoped_ptr.h" 129 | #include "crypto/openssl_util.h" 130 | #include "crypto/scoped_openssl_types.h" 131 | 132 | +#define SGX_ENABLE 133 | + 134 | namespace crypto { 135 | 136 | namespace { 137 | @@ -85,12 +90,28 @@ bool ExportKey(const void* key, 138 | ECPrivateKey::~ECPrivateKey() { 139 | if (key_) 140 | EVP_PKEY_free(key_); 141 | + if (public_key_) { 142 | + EVP_PKEY_free(public_key_); 143 | + } 144 | + if (key_blob_) 145 | + free(key_blob_); 146 | } 147 | 148 | ECPrivateKey* ECPrivateKey::Copy() const { 149 | scoped_ptr copy(new ECPrivateKey); 150 | if (key_) 151 | copy->key_ = EVP_PKEY_up_ref(key_); 152 | + 153 | + if (public_key_) 154 | + copy->public_key_ = EVP_PKEY_up_ref(public_key_); 155 | + 156 | + if (key_blob_) { 157 | + copy->key_blob_size_ = key_blob_size_; 158 | + copy->key_blob_ = (uint8_t *)calloc(key_blob_size_, sizeof(uint8_t)); 159 | + if (!copy->key_blob_) return NULL; 160 | + memcpy(copy->key_blob_, key_blob_, key_blob_size_); 161 | + } 162 | + 163 | return copy.release(); 164 | } 165 | 166 | @@ -112,6 +133,29 @@ ECPrivateKey* ECPrivateKey::Create() { 167 | } 168 | 169 | // static 170 | +ECPrivateKey* ECPrivateKey::CreateFromKeyBlobAndPublicKey( 171 | + uint8_t *sealed_key, 172 | + uint32_t sealed_key_size, 173 | + EC_KEY *public_key) { 174 | + OpenSSLErrStackTracer err_tracer(FROM_HERE); 175 | + 176 | + scoped_ptr result(new ECPrivateKey()); 177 | + 178 | + result->key_blob_ = (uint8_t *)calloc(sealed_key_size, sizeof(uint8_t)); 179 | + if (!result->key_blob_) return NULL; 180 | + memcpy(result->key_blob_, sealed_key, sealed_key_size); 181 | + 182 | + result->key_blob_size_ = sealed_key_size; 183 | + 184 | + result->public_key_ = EVP_PKEY_new(); 185 | + if (!result->public_key_ || 186 | + !EVP_PKEY_set1_EC_KEY(result->public_key_, public_key)) 187 | + return NULL; 188 | + 189 | + return result.release(); 190 | +} 191 | + 192 | +// static 193 | ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( 194 | const std::string& password, 195 | const std::vector& encrypted_private_key_info, 196 | @@ -124,6 +168,32 @@ ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( 197 | 198 | OpenSSLErrStackTracer err_tracer(FROM_HERE); 199 | 200 | +#ifdef SGX_ENABLE 201 | + // encrypted_private_key_info will be the key blob 202 | + uint8_t *sealed_key = (uint8_t *)&encrypted_private_key_info[0]; 203 | + uint32_t sealed_key_len = encrypted_private_key_info.size(); 204 | + 205 | + // turn subject_public_key_info into an EC KEY 206 | + size_t input_size = subject_public_key_info.size(); 207 | + uint8_t *input_arr = (uint8_t *)&subject_public_key_info[0]; 208 | + BIO *bio = BIO_new_mem_buf(input_arr, input_size); 209 | + if (!bio) 210 | + return NULL; 211 | + EVP_PKEY *evp_pubkey = d2i_PUBKEY_bio(bio, NULL); 212 | + if (!evp_pubkey) { 213 | + BIO_free(bio); 214 | + return NULL; 215 | + } 216 | + // gets reference without incrementing reference count 217 | + EC_KEY *public_key = EVP_PKEY_get0_EC_KEY(evp_pubkey); 218 | + ECPrivateKey *out = CreateFromKeyBlobAndPublicKey(sealed_key, 219 | + sealed_key_len, public_key); 220 | + 221 | + EVP_PKEY_free(evp_pubkey); 222 | + BIO_free(bio); 223 | + return out; 224 | +#endif 225 | + 226 | const uint8_t* data = &encrypted_private_key_info[0]; 227 | const uint8_t* ptr = data; 228 | ScopedX509_SIG p8_encrypted( 229 | @@ -152,6 +222,7 @@ ECPrivateKey* ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( 230 | 231 | // Create a new EVP_PKEY for it. 232 | scoped_ptr result(new ECPrivateKey); 233 | + 234 | result->key_ = EVP_PKCS82PKEY(p8_decrypted.get()); 235 | if (!result->key_ || EVP_PKEY_type(result->key_->type) != EVP_PKEY_EC) 236 | return NULL; 237 | @@ -163,6 +234,13 @@ bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password, 238 | int iterations, 239 | std::vector* output) { 240 | OpenSSLErrStackTracer err_tracer(FROM_HERE); 241 | + if (public_key_) { 242 | + // If the key was generated with SGX, it's already encrypted; 243 | + // put it directly into output. 244 | + output->insert(output->end(), &key_blob_[0], &key_blob_[key_blob_size_]); 245 | + return true; 246 | + } 247 | + 248 | // Convert into a PKCS#8 object. 249 | ScopedPKCS8_PRIV_KEY_INFO pkcs8(EVP_PKEY2PKCS8(key_)); 250 | if (!pkcs8.get()) 251 | @@ -192,6 +270,10 @@ bool ECPrivateKey::ExportEncryptedPrivateKey(const std::string& password, 252 | 253 | bool ECPrivateKey::ExportPublicKey(std::vector* output) { 254 | OpenSSLErrStackTracer err_tracer(FROM_HERE); 255 | + if (public_key_) 256 | + return ExportKeyWithBio( 257 | + public_key_, 258 | + reinterpret_cast(i2d_PUBKEY_bio), output); 259 | return ExportKeyWithBio( 260 | key_, reinterpret_cast(i2d_PUBKEY_bio), output); 261 | } 262 | @@ -200,15 +282,19 @@ bool ECPrivateKey::ExportRawPublicKey(std::string* output) { 263 | // i2d_PublicKey will produce an ANSI X9.62 public key which, for a P-256 264 | // key, is 0x04 (meaning uncompressed) followed by the x and y field 265 | // elements as 32-byte, big-endian numbers. 266 | + EVP_PKEY *key = key_; 267 | + if (public_key_) 268 | + key = public_key_; 269 | + 270 | static const int kExpectedKeyLength = 65; 271 | 272 | - int len = i2d_PublicKey(key_, NULL); 273 | + int len = i2d_PublicKey(key, NULL); 274 | if (len != kExpectedKeyLength) 275 | return false; 276 | 277 | uint8_t buf[kExpectedKeyLength]; 278 | uint8_t* derp = buf; 279 | - len = i2d_PublicKey(key_, &derp); 280 | + len = i2d_PublicKey(key, &derp); 281 | if (len != kExpectedKeyLength) 282 | return false; 283 | 284 | @@ -218,6 +304,9 @@ bool ECPrivateKey::ExportRawPublicKey(std::string* output) { 285 | 286 | bool ECPrivateKey::ExportValue(std::vector* output) { 287 | OpenSSLErrStackTracer err_tracer(FROM_HERE); 288 | + if (public_key_) 289 | + return false; 290 | + 291 | ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); 292 | return ExportKey(ec_key.get(), 293 | reinterpret_cast(i2d_ECPrivateKey), 294 | @@ -226,12 +315,15 @@ bool ECPrivateKey::ExportValue(std::vector* output) { 295 | 296 | bool ECPrivateKey::ExportECParams(std::vector* output) { 297 | OpenSSLErrStackTracer err_tracer(FROM_HERE); 298 | + if (public_key_) 299 | + return false; 300 | + 301 | ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(key_)); 302 | return ExportKey(ec_key.get(), 303 | reinterpret_cast(i2d_ECParameters), 304 | output); 305 | } 306 | 307 | -ECPrivateKey::ECPrivateKey() : key_(NULL) {} 308 | +ECPrivateKey::ECPrivateKey() : key_(NULL), key_blob_(NULL), public_key_(NULL) {} 309 | 310 | } // namespace crypto 311 | diff --git a/net/BUILD.gn b/net/BUILD.gn 312 | index 129003a..6f225ad 100644 313 | --- a/net/BUILD.gn 314 | +++ b/net/BUILD.gn 315 | @@ -104,6 +104,10 @@ net_shared_configs = [ 316 | "//build/config/compiler:no_size_t_to_int_warning", 317 | ] 318 | 319 | +if (is_linux) { 320 | + net_shared_configs += [ "//build/config/linux:sgx" ] 321 | +} 322 | + 323 | net_shared_public_deps = [ 324 | ":features", 325 | ":net_quic_proto", 326 | @@ -266,7 +270,9 @@ if (!is_nacl) { 327 | } 328 | 329 | if (is_linux) { 330 | - net_shared_configs += [ "//build/config/linux:libresolv" ] 331 | + net_shared_configs += [ 332 | + "//build/config/linux:libresolv", 333 | + ] 334 | } 335 | 336 | if (!use_nss_certs) { 337 | @@ -402,6 +408,9 @@ component("net") { 338 | cflags = [] 339 | configs += net_shared_configs 340 | public_configs = [ ":net_config" ] 341 | + if (is_linux) { 342 | + public_configs += [ "//build/config/linux:sgx" ] 343 | + } 344 | 345 | public_deps = net_shared_public_deps + [ "//url" ] 346 | deps = net_shared_deps 347 | diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h 348 | index 296024b..4402087 100644 349 | --- a/net/base/net_error_list.h 350 | +++ b/net/base/net_error_list.h 351 | @@ -794,6 +794,9 @@ NET_ERROR(CERT_DATABASE_CHANGED, -714) 352 | // Failure to import Channel ID. 353 | NET_ERROR(CHANNEL_ID_IMPORT_FAILED, -715) 354 | 355 | +// Failure to sign using Channel ID. 356 | +NET_ERROR(CHANNEL_ID_SIGN_FAILED, -716) 357 | + 358 | // DNS error codes. 359 | 360 | // DNS resolver received a malformed response. 361 | diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h 362 | index 7b7350b..dcc6ad2 100644 363 | --- a/net/log/net_log_event_type_list.h 364 | +++ b/net/log/net_log_event_type_list.h 365 | @@ -484,6 +484,12 @@ EVENT_TYPE(SSL_CHANNEL_ID_REQUESTED) 366 | // A channel ID was provided to the SSL library to be sent to the SSL server. 367 | EVENT_TYPE(SSL_CHANNEL_ID_PROVIDED) 368 | 369 | +// The SSL server requested that something be signed with a channel ID key. 370 | +EVENT_TYPE(SSL_CHANNEL_ID_SIGN_REQUESTED) 371 | + 372 | +// A channel ID was used to sign something requested by the SSL library. 373 | +EVENT_TYPE(SSL_CHANNEL_ID_SIGN_PROVIDED) 374 | + 375 | // A client certificate (or none) was provided to the SSL library to be sent 376 | // to the SSL server. 377 | // The following parameters are attached to the event: 378 | diff --git a/net/net.gypi b/net/net.gypi 379 | index eddea8a..cb9384c 100644 380 | --- a/net/net.gypi 381 | +++ b/net/net.gypi 382 | @@ -181,6 +181,10 @@ 383 | 'ssl/channel_id_service.h', 384 | 'ssl/channel_id_store.cc', 385 | 'ssl/channel_id_store.h', 386 | + 'ssl/channel_id_key_manager_u.c', 387 | + 'ssl/channel_id_key_manager_u.h', 388 | + 'ssl/sgx_util.cc', 389 | + 'ssl/sgx_util.h', 390 | 'ssl/client_key_store.cc', 391 | 'ssl/client_key_store.h', 392 | 'ssl/default_channel_id_store.cc', 393 | diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc 394 | index 9941436..97cf93f 100644 395 | --- a/net/socket/ssl_client_socket_openssl.cc 396 | +++ b/net/socket/ssl_client_socket_openssl.cc 397 | @@ -8,6 +8,7 @@ 398 | #include "net/socket/ssl_client_socket_openssl.h" 399 | 400 | #include 401 | +#include 402 | #include 403 | #include 404 | #include 405 | @@ -1133,6 +1134,12 @@ int SSLClientSocketOpenSSL::DoHandshake() { 406 | GotoState(STATE_CHANNEL_ID_LOOKUP); 407 | return OK; 408 | } 409 | + if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_SIGNATURE) { 410 | + // The server supports channel ID. Stop to sign before returning to 411 | + // the handshake. 412 | + GotoState(STATE_CHANNEL_ID_SIGN); 413 | + return OK; 414 | + } 415 | if (ssl_error == SSL_ERROR_WANT_X509_LOOKUP && 416 | !ssl_config_.send_client_cert) { 417 | return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 418 | @@ -1285,6 +1292,89 @@ int SSLClientSocketOpenSSL::DoChannelIDLookupComplete(int result) { 419 | return OK; 420 | } 421 | 422 | +int SSLClientSocketOpenSSL::DoChannelIDGetOrCreateAndSign() { 423 | + net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_SIGN_REQUESTED); 424 | + GotoState(STATE_CHANNEL_ID_SIGN_COMPLETE); 425 | + 426 | + return channel_id_service_->GetOrCreateChannelID( 427 | + host_and_port_.host(), &channel_id_key_, 428 | + base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete, 429 | + base::Unretained(this)), 430 | + &channel_id_request_); 431 | +} 432 | + 433 | +int SSLClientSocketOpenSSL::DoChannelIDGetOrCreateAndSignComplete(int result) { 434 | + if (result < 0) 435 | + return result; 436 | + 437 | + // Written by the |channel_id_service_|. 438 | + ECDSA_SIG *channel_id_signature = NULL; 439 | + // Written by the |channel_id_service_|. 440 | + EVP_PKEY *channel_id_public_key = NULL; 441 | + 442 | + // get digest from openssl 443 | + size_t digest_len = ssl_->tlsext_channel_id_digest_len; 444 | + uint8_t *digest = (uint8_t *)calloc(digest_len, sizeof(uint8_t)); 445 | + if (!digest) { 446 | + return -1; 447 | + } 448 | + crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 449 | + int rv = SSL_get_tls_channel_id_digest(ssl_, digest); 450 | + if (!rv) { 451 | + LOG(ERROR) << "Failed to get Channel ID digest to sign."; 452 | + int err = SSL_get_error(ssl_, rv); 453 | + free(digest); 454 | + return MapOpenSSLError(err, err_tracer); 455 | + } 456 | + 457 | + // sign 458 | + rv = channel_id_service_->SignDigest(digest, digest_len, &channel_id_signature, 459 | + &channel_id_public_key, 460 | + std::move(channel_id_key_)); 461 | + if (rv != OK || !channel_id_signature || !channel_id_public_key) { 462 | + LOG(ERROR) << "Failed to sign Channel ID digest."; 463 | + free(digest); 464 | + EVP_PKEY_free(channel_id_public_key); 465 | + ECDSA_SIG_free(channel_id_signature); 466 | + return ERR_CHANNEL_ID_SIGN_FAILED; 467 | + } 468 | + 469 | + // Hand the signature to OpenSSL. 470 | + // Check for error in case OpenSSL rejects the digest. 471 | + rv = SSL_set1_tls_channel_id_signature(ssl_, channel_id_signature); 472 | + if (!rv) { 473 | + LOG(ERROR) << "Failed to set Channel ID signature."; 474 | + int err = SSL_get_error(ssl_, rv); 475 | + free(digest); 476 | + EVP_PKEY_free(channel_id_public_key); 477 | + ECDSA_SIG_free(channel_id_signature); 478 | + return MapOpenSSLError(err, err_tracer); 479 | + } 480 | + 481 | + rv = SSL_set1_tls_channel_id_public_key(ssl_, channel_id_public_key); 482 | + if (!rv) { 483 | + LOG(ERROR) << "Failed to set Channel ID public key."; 484 | + int err = SSL_get_error(ssl_, rv); 485 | + free(digest); 486 | + EVP_PKEY_free(channel_id_public_key); 487 | + ECDSA_SIG_free(channel_id_signature); 488 | + return MapOpenSSLError(err, err_tracer); 489 | + } 490 | + 491 | + // free the ECDSA_SIG 492 | + ECDSA_SIG_free(channel_id_signature); 493 | + // free the public key 494 | + EVP_PKEY_free(channel_id_public_key); 495 | + // free the digest 496 | + free(digest); 497 | + 498 | + // Return to the handshake. 499 | + channel_id_sent_ = true; 500 | + net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_SIGN_PROVIDED); 501 | + GotoState(STATE_HANDSHAKE); 502 | + return OK; 503 | +} 504 | + 505 | int SSLClientSocketOpenSSL::DoVerifyCert(int result) { 506 | DCHECK(!server_cert_chain_->empty()); 507 | DCHECK(start_cert_verification_time_.is_null()); 508 | @@ -1505,6 +1595,13 @@ int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { 509 | case STATE_CHANNEL_ID_LOOKUP_COMPLETE: 510 | rv = DoChannelIDLookupComplete(rv); 511 | break; 512 | + case STATE_CHANNEL_ID_SIGN: 513 | + DCHECK_EQ(OK, rv); 514 | + rv = DoChannelIDGetOrCreateAndSign(); 515 | + break; 516 | + case STATE_CHANNEL_ID_SIGN_COMPLETE: 517 | + rv = DoChannelIDGetOrCreateAndSignComplete(rv); 518 | + break; 519 | case STATE_VERIFY_CERT: 520 | DCHECK_EQ(OK, rv); 521 | rv = DoVerifyCert(rv); 522 | diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h 523 | index 6dabb6a..9ef6840 100644 524 | --- a/net/socket/ssl_client_socket_openssl.h 525 | +++ b/net/socket/ssl_client_socket_openssl.h 526 | @@ -125,6 +125,8 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { 527 | int DoHandshakeComplete(int result); 528 | int DoChannelIDLookup(); 529 | int DoChannelIDLookupComplete(int result); 530 | + int DoChannelIDGetOrCreateAndSign(); 531 | + int DoChannelIDGetOrCreateAndSignComplete(int result); 532 | int DoVerifyCert(int result); 533 | int DoVerifyCertComplete(int result); 534 | void DoConnectCallback(int result); 535 | @@ -320,6 +322,8 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { 536 | STATE_HANDSHAKE_COMPLETE, 537 | STATE_CHANNEL_ID_LOOKUP, 538 | STATE_CHANNEL_ID_LOOKUP_COMPLETE, 539 | + STATE_CHANNEL_ID_SIGN, 540 | + STATE_CHANNEL_ID_SIGN_COMPLETE, 541 | STATE_VERIFY_CERT, 542 | STATE_VERIFY_CERT_COMPLETE, 543 | }; 544 | diff --git a/net/ssl/Makefile b/net/ssl/Makefile 545 | new file mode 100644 546 | index 0000000..ef84b12 547 | --- /dev/null 548 | +++ b/net/ssl/Makefile 549 | @@ -0,0 +1,92 @@ 550 | +# Copyright 2013 The Chromium Authors. All rights reserved. 551 | +# Use of this source code is governed by a BSD-style license that can be 552 | +# found in the LICENSE file. 553 | + 554 | +####### SGX SDK Settings ######## 555 | + 556 | +SGX_SDK ?= /opt/intel/sgxsdk 557 | +SGX_MODE ?= HW 558 | +SGX_ARCH ?= x64 559 | +SGX_PRERELEASE ?= 1 560 | +SGX_DEBUG ?= 0 561 | + 562 | +ifeq ($(shell getconf LONG_BIT), 32) 563 | + SGX_ARCH := x86 564 | +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) 565 | + SGX_ARCH := x86 566 | +endif 567 | + 568 | +ifeq ($(SGX_ARCH), x86) 569 | + SGX_COMMON_CFLAGS := -m32 570 | + SGX_LIBRARY_PATH := $(SGX_SDK)/lib 571 | + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign 572 | + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r 573 | +else 574 | + SGX_COMMON_CFLAGS := -m64 575 | + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 576 | + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign 577 | + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r 578 | +endif 579 | + 580 | + 581 | +######## Enclave Settings ######## 582 | + 583 | +ifneq ($(SGX_MODE), HW) 584 | + Trts_Library_Name := sgx_trts_sim 585 | + Service_Library_Name := sgx_tservice_sim 586 | +else 587 | + Trts_Library_Name := sgx_trts 588 | + Service_Library_Name := sgx_tservice 589 | +endif 590 | + 591 | +Enclave_C_Files := channel_id_enclave/channel_id_key_manager.c 592 | +Enclave_Include_Paths := -Ichannel_id_enclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport 593 | + 594 | +Enclave_Compile_Flags := -O3 -fPIC -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) 595 | +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ 596 | + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ 597 | + -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -lsgx_tcrypto -l$(Service_Library_Name) -Wl,--end-group \ 598 | + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ 599 | + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ 600 | + -Wl,--defsym,__ImageBase=0 \ 601 | + -Wl,--version-script=channel_id_enclave/channel_id_key_manager.lds 602 | + 603 | +Enclave_C_Objects := $(Enclave_C_Files:.c=.o) 604 | + 605 | +all: channel_id_key_manager_u.c channel_id_key_manager.signed.so 606 | + @echo "Untrusted Channel ID key manager stub created." 607 | + @echo "Channel ID key manager enclave created." 608 | + 609 | +enclave: channel_id_key_manager.signed.so 610 | + @echo "Channel ID key manager enclave created." 611 | + 612 | +######## Enclave Objects ######## 613 | + 614 | +channel_id_key_manager_u.c: $(SGX_EDGER8R) channel_id_enclave/channel_id_key_manager.edl 615 | + @$(SGX_EDGER8R) --untrusted channel_id_enclave/channel_id_key_manager.edl --search-path channel_id_enclave --search-path $(SGX_SDK)/include 616 | + @echo "GEN => $@" 617 | + 618 | +channel_id_enclave/channel_id_key_manager_t.c: $(SGX_EDGER8R) channel_id_enclave/channel_id_key_manager.edl 619 | + @cd channel_id_enclave && $(SGX_EDGER8R) --trusted ../channel_id_enclave/channel_id_key_manager.edl --search-path ../channel_id_enclave --search-path $(SGX_SDK)/include 620 | + @echo "GEN => $@" 621 | + 622 | +channel_id_enclave/channel_id_key_manager_t.o: channel_id_enclave/channel_id_key_manager_t.c 623 | + @$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_Compile_Flags) -c $< -o $@ 624 | + @echo "CC <= $<" 625 | + 626 | +channel_id_enclave/%.o: channel_id_enclave/%.c 627 | + @$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_Compile_Flags) -c $< -o $@ 628 | + @echo "CC <= $<" 629 | + 630 | +channel_id_enclave/channel_id_key_manager.so: channel_id_enclave/channel_id_key_manager_t.o $(Enclave_C_Objects) 631 | + @$(CC) $(SGX_COMMON_CFLAGS) $^ -shared -o $@ $(Enclave_Link_Flags) 632 | + @echo "LINK => $@" 633 | + 634 | +channel_id_key_manager.signed.so: channel_id_enclave/channel_id_key_manager.so 635 | + @LD_LIBRARY_PATH=$(SGX_LIBRARY_PATH) $(SGX_ENCLAVE_SIGNER) sign -key channel_id_enclave/channel_id_key_manager_private.pem -enclave $< -out $@ -config channel_id_enclave/channel_id_key_manager.config.xml 636 | + @echo "SIGN => $@" 637 | + 638 | +.PHONY: clean 639 | + 640 | +clean: 641 | + @rm -f $(Enclave_C_Objects) channel_id_enclave/*.so channel_id_enclave/channel_id_key_manager_t.* channel_id_key_manager_u.* *.log 642 | diff --git a/net/ssl/channel_id_enclave/channel_id_key_manager.c b/net/ssl/channel_id_enclave/channel_id_key_manager.c 643 | new file mode 100644 644 | index 0000000..415fe6c 645 | --- /dev/null 646 | +++ b/net/ssl/channel_id_enclave/channel_id_key_manager.c 647 | @@ -0,0 +1,101 @@ 648 | +// Copyright 2013 The Chromium Authors. All rights reserved. 649 | +// Use of this source code is governed by a BSD-style license that can be 650 | +// found in the LICENSE file. 651 | + 652 | +#include 653 | +// SGX SDK API for sealing and unsealing functionalities 654 | +// Requirements: libsgx_tservice.a (HW) or libsgx_tservice_sim.a (simulation mode) 655 | +#include 656 | +// SGX SDK Internals 657 | +// Requirements: libsgx_trts.a (HW) or libsgx_trts_sim.a (simulation mode) 658 | +#include 659 | + 660 | +// Prototype declarations for trusted proxies and bridges 661 | +#include "channel_id_key_manager_t.h" 662 | + 663 | +sgx_ecc_state_handle_t ecc_handle; 664 | + 665 | +// Enclave Functions 666 | +// Applications can call these functions by making Enclave Calls (ECALLS) using the untrusted proxy function generated by the sgx_edger8r tool 667 | + 668 | +uint32_t GenerateSealedECKey( 669 | + uint8_t *sealed_key, 670 | + int sealed_key_size, 671 | + uint8_t *public_key_out, 672 | + int public_key_size) { 673 | + sgx_status_t ret = sgx_ecc256_open_context(&ecc_handle); 674 | + if (ret != SGX_SUCCESS) { 675 | + return 1; 676 | + } 677 | + 678 | + sgx_ec256_private_t private_key; 679 | + sgx_ec256_public_t *public_key = (sgx_ec256_public_t *) public_key_out; 680 | + 681 | + // public key output directly 682 | + ret = sgx_ecc256_create_key_pair(&private_key, public_key, ecc_handle); 683 | + if (ret != SGX_SUCCESS) { 684 | + return 2; 685 | + } 686 | + 687 | + ret = sgx_ecc256_close_context(ecc_handle); 688 | + 689 | + // seal key and output sealed key 690 | + uint32_t result = 0; 691 | + sgx_sealed_data_t *sealed_key_data = (sgx_sealed_data_t *) sealed_key; 692 | + 693 | + result = sgx_seal_data(0, NULL, sizeof(private_key), (uint8_t *)&private_key, 694 | + sealed_key_size, sealed_key_data); 695 | + 696 | + return result; 697 | +} 698 | + 699 | +// returns 2 on invalid parameter to unseal 700 | +// returns 1 on failure to open context 701 | +// returns 4 if signature size is too small 702 | +// returns 3 on failure to sign 703 | +// returns 0 on success 704 | +uint32_t SignUsingSealedKey(uint8_t *message, int message_size, 705 | + uint8_t *signature_out, int signature_size, 706 | + uint8_t *sealed_key_in, int sealed_key_size) { 707 | + // unseal key 708 | + sgx_ec256_private_t private_key; 709 | + 710 | + int32_t result = 0; 711 | + sgx_sealed_data_t *sealed_key = (sgx_sealed_data_t *) sealed_key_in; 712 | + // PrintString("Inside Enclave: Unsealing Password.\n"); 713 | + int clear_private_key_size = sizeof(sgx_ec256_private_t); 714 | + result = sgx_unseal_data(sealed_key, 715 | + NULL, // optional, but check how to mark it optional 716 | + NULL, 717 | + (uint8_t *) &private_key, 718 | + &clear_private_key_size); 719 | + if (result != 0) { 720 | + return result; 721 | + } 722 | + 723 | + // sign 724 | + sgx_ec256_signature_t *signature = (sgx_ec256_signature_t *)signature_out; 725 | + 726 | + if (signature_size < sizeof(sgx_ec256_signature_t)) { 727 | + return 4; 728 | + } 729 | + 730 | + sgx_status_t ret = sgx_ecc256_open_context(&ecc_handle); 731 | + if (ret != SGX_SUCCESS) { 732 | + return 1; 733 | + } 734 | + 735 | + ret = sgx_ecdsa_sign(message, message_size, &private_key, signature, 736 | + ecc_handle); 737 | + if (ret != SGX_SUCCESS) { 738 | + return 3; 739 | + } 740 | + 741 | + ret = sgx_ecc256_close_context(ecc_handle); 742 | + return 0; 743 | +} 744 | + 745 | +uint32_t CalculateSealedKeySize(uint32_t *size) { 746 | + *size = sgx_calc_sealed_data_size(0, sizeof(sgx_ec256_private_t)); 747 | + return 0; 748 | +} 749 | diff --git a/net/ssl/channel_id_enclave/channel_id_key_manager.config.xml b/net/ssl/channel_id_enclave/channel_id_key_manager.config.xml 750 | new file mode 100644 751 | index 0000000..5e75a02 752 | --- /dev/null 753 | +++ b/net/ssl/channel_id_enclave/channel_id_key_manager.config.xml 754 | @@ -0,0 +1,11 @@ 755 | + 756 | + 757 | + 758 | + 759 | + 0 760 | + 0 761 | + 0x40000 762 | + 0x100000 763 | + 10 764 | + 0 765 | + 766 | diff --git a/net/ssl/channel_id_enclave/channel_id_key_manager.edl b/net/ssl/channel_id_enclave/channel_id_key_manager.edl 767 | new file mode 100644 768 | index 0000000..2d5cab7 769 | --- /dev/null 770 | +++ b/net/ssl/channel_id_enclave/channel_id_key_manager.edl 771 | @@ -0,0 +1,22 @@ 772 | +// Copyright 2013 The Chromium Authors. All rights reserved. 773 | +// Use of this source code is governed by a BSD-style license that can be 774 | +// found in the LICENSE file. 775 | + 776 | +enclave { 777 | + trusted { 778 | + public uint32_t GenerateSealedECKey( 779 | + [out, size=sealed_key_size] uint8_t *sealed_key, 780 | + int sealed_key_size, 781 | + [out, size=public_key_size] uint8_t *public_key, 782 | + int public_key_size); 783 | + public uint32_t SignUsingSealedKey( 784 | + [in, size=message_size] uint8_t *message, 785 | + int message_size, 786 | + [out, size=signature_size] uint8_t *signature, 787 | + int signature_size, 788 | + [in, size=sealed_key_size] uint8_t *sealed_key, 789 | + int sealed_key_size); 790 | + public uint32_t CalculateSealedKeySize( 791 | + [out, size=4] uint32_t *size); 792 | + }; 793 | +}; 794 | diff --git a/net/ssl/channel_id_enclave/channel_id_key_manager.lds b/net/ssl/channel_id_enclave/channel_id_key_manager.lds 795 | new file mode 100644 796 | index 0000000..900d8d1 797 | --- /dev/null 798 | +++ b/net/ssl/channel_id_enclave/channel_id_key_manager.lds 799 | @@ -0,0 +1,13 @@ 800 | +// Copyright 2013 The Chromium Authors. All rights reserved. 801 | +// Use of this source code is governed by a BSD-style license that can be 802 | +// found in the LICENSE file. 803 | + 804 | +channel_id_key_manager.so 805 | +{ 806 | + global: 807 | + g_global_data_sim; 808 | + g_global_data; 809 | + enclave_entry; 810 | + local: 811 | + *; 812 | +}; 813 | diff --git a/net/ssl/channel_id_enclave/channel_id_key_manager_private.pem b/net/ssl/channel_id_enclave/channel_id_key_manager_private.pem 814 | new file mode 100644 815 | index 0000000..529d07b 816 | --- /dev/null 817 | +++ b/net/ssl/channel_id_enclave/channel_id_key_manager_private.pem 818 | @@ -0,0 +1,39 @@ 819 | +-----BEGIN RSA PRIVATE KEY----- 820 | +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ 821 | +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ 822 | +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr 823 | +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b 824 | +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H 825 | +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD 826 | +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW 827 | +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC 828 | +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe 829 | +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z 830 | +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q 831 | +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 832 | +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 833 | +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 834 | +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 835 | +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm 836 | +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i 837 | +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 838 | +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd 839 | +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD 840 | +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a 841 | +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC 842 | +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ 843 | +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo 844 | +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t 845 | +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz 846 | +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 847 | +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 848 | +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom 849 | +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G 850 | +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv 851 | +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN 852 | +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 853 | +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp 854 | +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg 855 | +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH 856 | +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= 857 | +-----END RSA PRIVATE KEY----- 858 | diff --git a/net/ssl/channel_id_service.cc b/net/ssl/channel_id_service.cc 859 | index e17b813..6d66695 100644 860 | --- a/net/ssl/channel_id_service.cc 861 | +++ b/net/ssl/channel_id_service.cc 862 | @@ -5,9 +5,15 @@ 863 | #include "net/ssl/channel_id_service.h" 864 | 865 | #include 866 | +#include 867 | #include 868 | #include 869 | 870 | +#include 871 | +#include 872 | +#include 873 | +#include 874 | + 875 | #include "base/bind.h" 876 | #include "base/bind_helpers.h" 877 | #include "base/callback_helpers.h" 878 | @@ -34,6 +40,34 @@ 879 | #include // PR_DetachThread 880 | #endif 881 | 882 | +#define SGX_ENABLE 883 | + 884 | +// Define SGX_ENABLE for sealing private keys in SGX 885 | + 886 | +#define CIDSDEBUG(x) { \ 887 | + std::cout << __func__ << ": " << x << "\n"; \ 888 | +} 889 | + 890 | +#ifdef SGX_ENABLE 891 | +// Prototype Declarations for untrusted proxies and bridges. This is 892 | +// generated by the edger8r tool and along with the trusted counterpart 893 | +// provide an interface between the untrusted application and the enclave 894 | +#include "net/ssl/channel_id_key_manager_u.h" 895 | + 896 | +// Provides API for Creating and Destroying Enclaves to the Application 897 | +// Requirements: libsgx_urts.so (HW Mode) or libsgx_urts_sim.so (Simulation Mode) 898 | +#include 899 | + 900 | +// Provides Utilities for sealing and unsealing: Confidentiality and integrity 901 | +// protection of data outside an enclave 902 | +// Requirements: libsgx_tservice.a (HW Mode) or libsgx_tservice_sim.a (Simulation Mode) 903 | +#include 904 | + 905 | +#include 906 | + 907 | +#include "net/ssl/sgx_util.h" 908 | +#endif 909 | + 910 | namespace net { 911 | 912 | namespace { 913 | @@ -85,14 +119,80 @@ void RecordGetChannelIDTime(base::TimeDelta request_time) { 914 | // unjoined thread, due to relying on a non-leaked LazyInstance 915 | scoped_ptr GenerateChannelID( 916 | const std::string& server_identifier, 917 | +#ifdef SGX_ENABLE 918 | + std::shared_ptr sgx_enclave_id, 919 | +#endif 920 | int* error) { 921 | scoped_ptr result; 922 | 923 | base::TimeTicks start = base::TimeTicks::Now(); 924 | base::Time creation_time = base::Time::Now(); 925 | + 926 | + // If SGX fails, we fall back to non-SGX behavior. 927 | + 928 | + 929 | +#ifdef SGX_ENABLE 930 | + uint32_t retval = 0; 931 | + uint32_t sealed_key_size = 0; 932 | + if (!sgx_enclave_id || sgx_enclave_id->eid() == 0) { 933 | + CIDSDEBUG("No eid available."); 934 | + *error = ERR_KEY_GENERATION_FAILED; 935 | + return result; 936 | + } 937 | + retval = CalculateSealedKeySize(sgx_enclave_id->eid(), &retval, &sealed_key_size); 938 | + if (sealed_key_size == 0) { 939 | + CIDSDEBUG("Sealed key size is zero with eid " << sgx_enclave_id->eid()); 940 | + *error = ERR_KEY_GENERATION_FAILED; 941 | + return result; 942 | + } 943 | + uint8_t *sealed_key = (uint8_t *)calloc(sealed_key_size, sizeof(uint8_t)); 944 | + if (!sealed_key) { 945 | + CIDSDEBUG("Out of memory."); 946 | + *error = ERR_KEY_GENERATION_FAILED; 947 | + return result; 948 | + } 949 | + sgx_ec256_public_t sgx_public_key; 950 | + uint32_t public_key_size = sizeof(sgx_ec256_public_t); 951 | + sgx_status_t status = GenerateSealedECKey(sgx_enclave_id->eid(), &retval, 952 | + sealed_key, sealed_key_size, (uint8_t *)&sgx_public_key, public_key_size); 953 | + if (status != SGX_SUCCESS) { 954 | + CIDSDEBUG("Key generation failed with return value " << retval << "."); 955 | + *error = ERR_KEY_GENERATION_FAILED; 956 | + free(sealed_key); 957 | + return result; 958 | + } 959 | + 960 | + // Using the same curve as in ECPrivateKey::Create. 961 | + EC_KEY *public_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 962 | + if (!public_key) { 963 | + CIDSDEBUG("Trouble creating EC KEY."); 964 | + *error = ERR_KEY_GENERATION_FAILED; 965 | + return result; 966 | + } 967 | + // get bignum x and y from SGX 968 | + BIGNUM *x = LittleEndianArrayToBIGNUMuint8_t(sgx_public_key.gx, 969 | + SGX_ECP256_KEY_SIZE); 970 | + BIGNUM *y = LittleEndianArrayToBIGNUMuint8_t(sgx_public_key.gy, 971 | + SGX_ECP256_KEY_SIZE); 972 | + retval = EC_KEY_set_public_key_affine_coordinates(public_key, x, y); 973 | + if (!retval) { 974 | + CIDSDEBUG("Could not set public key coordinates."); 975 | + *error = ERR_KEY_GENERATION_FAILED; 976 | + return result; 977 | + } 978 | + BN_free(x); 979 | + BN_free(y); 980 | + scoped_ptr key( 981 | + crypto::ECPrivateKey::CreateFromKeyBlobAndPublicKey(sealed_key, 982 | + sealed_key_size, public_key)); 983 | + free(sealed_key); 984 | + EC_KEY_free(public_key); 985 | +#else 986 | scoped_ptr key(crypto::ECPrivateKey::Create()); 987 | +#endif 988 | 989 | if (!key) { 990 | + CIDSDEBUG("No key made."); 991 | DLOG(ERROR) << "Unable to create channel ID key pair"; 992 | *error = ERR_KEY_GENERATION_FAILED; 993 | return result; 994 | @@ -122,9 +222,16 @@ class ChannelIDServiceWorker { 995 | scoped_ptr)> WorkerDoneCallback; 996 | 997 | ChannelIDServiceWorker(const std::string& server_identifier, 998 | - const WorkerDoneCallback& callback) 999 | +#ifdef SGX_ENABLE 1000 | + std::shared_ptr sgx_enclave_id, 1001 | +#endif 1002 | + const WorkerDoneCallback& callback 1003 | + ) 1004 | : server_identifier_(server_identifier), 1005 | origin_task_runner_(base::ThreadTaskRunnerHandle::Get()), 1006 | +#ifdef SGX_ENABLE 1007 | + sgx_enclave_id_(sgx_enclave_id), 1008 | +#endif 1009 | callback_(callback) {} 1010 | 1011 | // Starts the worker on |task_runner|. If the worker fails to start, such as 1012 | @@ -143,7 +250,11 @@ class ChannelIDServiceWorker { 1013 | // Runs on a worker thread. 1014 | int error = ERR_FAILED; 1015 | scoped_ptr channel_id = 1016 | - GenerateChannelID(server_identifier_, &error); 1017 | + GenerateChannelID(server_identifier_, 1018 | +#ifdef SGX_ENABLE 1019 | + sgx_enclave_id_, 1020 | +#endif 1021 | + &error); 1022 | #if !defined(USE_OPENSSL) 1023 | // Detach the thread from NSPR. 1024 | // Calling NSS functions attaches the thread to NSPR, which stores 1025 | @@ -161,6 +272,9 @@ class ChannelIDServiceWorker { 1026 | 1027 | const std::string server_identifier_; 1028 | scoped_refptr origin_task_runner_; 1029 | +#ifdef SGX_ENABLE 1030 | + std::shared_ptr sgx_enclave_id_; 1031 | +#endif 1032 | WorkerDoneCallback callback_; 1033 | 1034 | DISALLOW_COPY_AND_ASSIGN(ChannelIDServiceWorker); 1035 | @@ -203,6 +317,7 @@ class ChannelIDServiceJob { 1036 | for (std::vector::iterator i = requests.begin(); 1037 | i != requests.end(); i++) { 1038 | scoped_ptr key_copy; 1039 | + 1040 | if (key) 1041 | key_copy.reset(key->Copy()); 1042 | (*i)->Post(error, std::move(key_copy)); 1043 | @@ -292,6 +407,9 @@ ChannelIDService::ChannelIDService( 1044 | key_store_hits_(0), 1045 | inflight_joins_(0), 1046 | workers_created_(0), 1047 | +#ifdef SGX_ENABLE 1048 | + sgx_enclave_id_(std::make_shared()), 1049 | +#endif 1050 | weak_ptr_factory_(this) { 1051 | } 1052 | 1053 | @@ -309,6 +427,59 @@ std::string ChannelIDService::GetDomainForHost(const std::string& host) { 1054 | return domain; 1055 | } 1056 | 1057 | +int ChannelIDService::SignDigest(uint8_t *digest, 1058 | + size_t digest_len, 1059 | + ECDSA_SIG **signature, 1060 | + EVP_PKEY **public_key, 1061 | + scoped_ptr key) { 1062 | +#ifdef SGX_ENABLE 1063 | + base::TimeTicks start = base::TimeTicks::Now(); 1064 | + // Sign using the retrieved key, in channel_id_key_. 1065 | + // It will be an ECPrivateKey, created with SGX. 1066 | + // Retrieve the opaque blob, and pass it to the enclave. 1067 | + int signature_size = sizeof(sgx_ec256_signature_t); 1068 | + sgx_ec256_signature_t ui_signature; 1069 | + 1070 | + uint8_t *sealed_key = key->key_blob(); 1071 | + if (!sealed_key) { 1072 | + CIDSDEBUG("No sealed key available."); 1073 | + return -1; 1074 | + } 1075 | + uint32_t sealed_key_size = key->key_blob_size(); 1076 | + 1077 | + uint32_t retval = 0; 1078 | + if (!sgx_enclave_id_ || sgx_enclave_id_->eid() == 0) { 1079 | + return -1; 1080 | + } 1081 | + SignUsingSealedKey(sgx_enclave_id_->eid(), &retval, digest, digest_len, 1082 | + (uint8_t *)&ui_signature, signature_size, 1083 | + sealed_key, sealed_key_size); 1084 | + 1085 | + 1086 | + // put a copy of the public key in |public_key| 1087 | + *public_key = EVP_PKEY_up_ref(key->public_key()); 1088 | + if (!key->public_key()) { 1089 | + return -1; 1090 | + } 1091 | + 1092 | + // enclave should put the signature into |signature| 1093 | + ECDSA_SIG *sig = ECDSA_SIG_new(); 1094 | + sig->r = LittleEndianArrayToBIGNUMuint8_t((uint8_t *)ui_signature.x, 1095 | + SGX_NISTP_ECP256_KEY_SIZE * sizeof(uint32_t)); 1096 | + sig->s = LittleEndianArrayToBIGNUMuint8_t((uint8_t *)ui_signature.y, 1097 | + SGX_NISTP_ECP256_KEY_SIZE * sizeof(uint32_t)); 1098 | + 1099 | + *signature = sig; 1100 | + UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.SignDigestTime", 1101 | + base::TimeTicks::Now() - start, 1102 | + base::TimeDelta::FromMilliseconds(1), 1103 | + base::TimeDelta::FromMinutes(5), 1104 | + 50); 1105 | + return OK; 1106 | +#endif 1107 | + return -1; 1108 | +} 1109 | + 1110 | int ChannelIDService::GetOrCreateChannelID( 1111 | const std::string& host, 1112 | scoped_ptr* key, 1113 | @@ -345,6 +516,9 @@ int ChannelIDService::GetOrCreateChannelID( 1114 | workers_created_++; 1115 | ChannelIDServiceWorker* worker = new ChannelIDServiceWorker( 1116 | domain, 1117 | +#ifdef SGX_ENABLE 1118 | + sgx_enclave_id_, 1119 | +#endif 1120 | base::Bind(&ChannelIDService::GeneratedChannelID, 1121 | weak_ptr_factory_.GetWeakPtr())); 1122 | if (!worker->Start(task_runner_)) { 1123 | @@ -429,6 +603,9 @@ void ChannelIDService::GotChannelID(int err, 1124 | workers_created_++; 1125 | ChannelIDServiceWorker* worker = new ChannelIDServiceWorker( 1126 | server_identifier, 1127 | +#ifdef SGX_ENABLE 1128 | + sgx_enclave_id_, 1129 | +#endif 1130 | base::Bind(&ChannelIDService::GeneratedChannelID, 1131 | weak_ptr_factory_.GetWeakPtr())); 1132 | if (!worker->Start(task_runner_)) { 1133 | diff --git a/net/ssl/channel_id_service.h b/net/ssl/channel_id_service.h 1134 | index eb4a92a..7a87611 100644 1135 | --- a/net/ssl/channel_id_service.h 1136 | +++ b/net/ssl/channel_id_service.h 1137 | @@ -11,7 +11,8 @@ 1138 | #include 1139 | #include 1140 | 1141 | -#include "base/macros.h" 1142 | +#include 1143 | + 1144 | #include "base/memory/scoped_ptr.h" 1145 | #include "base/memory/weak_ptr.h" 1146 | #include "base/threading/non_thread_safe.h" 1147 | @@ -20,6 +21,12 @@ 1148 | #include "net/base/net_export.h" 1149 | #include "net/ssl/channel_id_store.h" 1150 | 1151 | +#define SGX_ENABLE 1152 | + 1153 | +#ifdef SGX_ENABLE 1154 | +#include "net/ssl/sgx_util.h" 1155 | +#endif 1156 | + 1157 | namespace base { 1158 | class TaskRunner; 1159 | } // namespace base 1160 | @@ -106,6 +113,20 @@ class NET_EXPORT ChannelIDService 1161 | const CompletionCallback& callback, 1162 | Request* out_req); 1163 | 1164 | + // Signs the digests given in |digest| using |key|. 1165 | + // Puts the result into |signature|. Also puts the public key into 1166 | + // |public_key| (this could be done in the caller, here for convenience). 1167 | + // 1168 | + // Returns OK if successful or an error code upon failure. 1169 | + // 1170 | + // On successful completion, |signature| holds the ECDSA signature. 1171 | + // Caller is responsible for calling |ECDSA_SIG_free|. 1172 | + int SignDigest(uint8_t *digest, 1173 | + size_t digest_len, 1174 | + ECDSA_SIG **signature, 1175 | + EVP_PKEY **public_key, 1176 | + scoped_ptr key); 1177 | + 1178 | // Fetches the channel ID for the specified host if one exists. 1179 | // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error 1180 | // code upon failure. 1181 | @@ -181,6 +202,10 @@ class NET_EXPORT ChannelIDService 1182 | uint64_t inflight_joins_; 1183 | uint64_t workers_created_; 1184 | 1185 | +#ifdef SGX_ENABLE 1186 | + std::shared_ptr sgx_enclave_id_; 1187 | +#endif 1188 | + 1189 | base::WeakPtrFactory weak_ptr_factory_; 1190 | 1191 | DISALLOW_COPY_AND_ASSIGN(ChannelIDService); 1192 | diff --git a/net/ssl/channel_id_service_unittest.cc b/net/ssl/channel_id_service_unittest.cc 1193 | index 1e98b61..48fb791 100644 1194 | --- a/net/ssl/channel_id_service_unittest.cc 1195 | +++ b/net/ssl/channel_id_service_unittest.cc 1196 | @@ -4,6 +4,7 @@ 1197 | 1198 | #include "net/ssl/channel_id_service.h" 1199 | 1200 | +#include 1201 | #include 1202 | #include 1203 | 1204 | @@ -150,6 +151,41 @@ TEST_F(ChannelIDServiceTest, GetCacheMiss) { 1205 | EXPECT_FALSE(key); 1206 | } 1207 | 1208 | +TEST_F(ChannelIDServiceTest, SignDigest) { 1209 | + std::string host("encrypted.google.com"); 1210 | + 1211 | + int error; 1212 | + TestCompletionCallback callback; 1213 | + ChannelIDService::Request request; 1214 | + 1215 | + // Generate key. 1216 | + scoped_ptr key1; 1217 | + EXPECT_EQ(0, service_->channel_id_count()); 1218 | + error = service_->GetOrCreateChannelID(host, &key1, callback.callback(), 1219 | + &request); 1220 | + EXPECT_EQ(ERR_IO_PENDING, error); 1221 | + EXPECT_TRUE(request.is_active()); 1222 | + error = callback.WaitForResult(); 1223 | + EXPECT_EQ(OK, error); 1224 | + EXPECT_EQ(1, service_->channel_id_count()); 1225 | + EXPECT_TRUE(key1); 1226 | + EXPECT_FALSE(request.is_active()); 1227 | + 1228 | + // Sign digest. 1229 | + char str[] = "Test string."; 1230 | + uint8_t* digest = (uint8_t *)str; 1231 | + size_t digest_len = 13; 1232 | + ECDSA_SIG *signature; 1233 | + EVP_PKEY *public_key; 1234 | + error = service_->SignDigest(digest, digest_len, &signature, 1235 | + &public_key, std::move(key1)); 1236 | + EXPECT_EQ(OK, error); 1237 | + EXPECT_TRUE(public_key); 1238 | + EXPECT_TRUE(signature); 1239 | + ECDSA_SIG_free(signature); 1240 | + EVP_PKEY_free(public_key); 1241 | +} 1242 | + 1243 | TEST_F(ChannelIDServiceTest, CacheHit) { 1244 | std::string host("encrypted.google.com"); 1245 | 1246 | diff --git a/net/ssl/sgx_util.cc b/net/ssl/sgx_util.cc 1247 | new file mode 100644 1248 | index 0000000..c709dd8 1249 | --- /dev/null 1250 | +++ b/net/ssl/sgx_util.cc 1251 | @@ -0,0 +1,83 @@ 1252 | +// Copyright 2013 The Chromium Authors. All rights reserved. 1253 | +// Use of this source code is governed by a BSD-style license that can be 1254 | +// found in the LICENSE file. 1255 | + 1256 | +#include "net/ssl/sgx_util.h" 1257 | + 1258 | +#include 1259 | +#include 1260 | +#include 1261 | + 1262 | +#include "base/logging.h" 1263 | +#include "base/metrics/histogram_macros.h" 1264 | + 1265 | +// SGX Enclave path 1266 | +#define ENCLAVE_PATH "/home/ebp/chromium/src/net/ssl/channel_id_key_manager.signed.so" 1267 | + 1268 | +sgx_enclave_id_t CreateEnclave(); 1269 | +void DestroyEnclave(sgx_enclave_id_t eid); 1270 | + 1271 | +#define CIDSDEBUG(x) { \ 1272 | + std::cout << __func__ << ": " << x << "\n"; \ 1273 | +} 1274 | + 1275 | +namespace net { 1276 | + 1277 | +SGXEnclaveID::SGXEnclaveID() : eid_(CreateEnclave()) {} 1278 | + 1279 | +SGXEnclaveID::~SGXEnclaveID() { 1280 | + DestroyEnclave(eid_); 1281 | +} 1282 | + 1283 | +} //namespace net 1284 | + 1285 | +// for SGX 1286 | +// allocates a BIGNUM 1287 | +// Note: this has only been tested on a little endian machine. 1288 | + 1289 | +BIGNUM *LittleEndianArrayToBIGNUMuint8_t(uint8_t *arr, uint32_t arr_len) { 1290 | + uint8_t arr_copy[arr_len]; 1291 | + 1292 | + memcpy(arr_copy, arr, arr_len); 1293 | + 1294 | + // convert from little endian to big endian 1295 | + std::reverse(arr_copy, arr_copy + arr_len); 1296 | + 1297 | + // convert to BIGNUM 1298 | + return BN_bin2bn(arr_copy, arr_len, NULL); 1299 | +} 1300 | + 1301 | +sgx_enclave_id_t CreateEnclave() { 1302 | + // Create SGX enclave on construction 1303 | + int launch_token_update = 0; 1304 | + // Launch token created by enclave licensing service, holds enclave license information 1305 | + sgx_launch_token_t launch_token; 1306 | + memset(&launch_token, 0, sizeof(sgx_launch_token_t)); 1307 | + sgx_enclave_id_t eid = 0; 1308 | + // Create Enclave SDK call 1309 | + // Enclave ID, used for referring to the enclave, returned 1310 | + 1311 | + CIDSDEBUG("Creating enclave ..."); 1312 | + sgx_status_t ret = SGX_ERROR_SERVICE_UNAVAILABLE; 1313 | + base::TimeTicks start = base::TimeTicks::Now(); 1314 | + ret = sgx_create_enclave(ENCLAVE_PATH, 1, &launch_token, 1315 | + &launch_token_update, &eid, NULL); 1316 | + if (ret == SGX_SUCCESS) { 1317 | + UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.EnclaveCreationTime", 1318 | + base::TimeTicks::Now() - start, 1319 | + base::TimeDelta::FromMilliseconds(1), 1320 | + base::TimeDelta::FromMinutes(5), 1321 | + 50); 1322 | + CIDSDEBUG("Enclave successfully created, eid: " << eid); 1323 | + } else { 1324 | + CIDSDEBUG("Enclave load failed, SGX return: " << ret); 1325 | + } 1326 | + return eid; 1327 | +} 1328 | + 1329 | +void DestroyEnclave(sgx_enclave_id_t eid) { 1330 | + if (eid != 0) { 1331 | + CIDSDEBUG("Destroying enclave, eid: " << eid); 1332 | + sgx_destroy_enclave(eid); 1333 | + } 1334 | +} 1335 | diff --git a/net/ssl/sgx_util.h b/net/ssl/sgx_util.h 1336 | new file mode 100644 1337 | index 0000000..f4c458b 1338 | --- /dev/null 1339 | +++ b/net/ssl/sgx_util.h 1340 | @@ -0,0 +1,30 @@ 1341 | +// Copyright 2013 The Chromium Authors. All rights reserved. 1342 | +// Use of this source code is governed by a BSD-style license that can be 1343 | +// found in the LICENSE file. 1344 | + 1345 | +#ifndef NET_SSL_SGX_UTIL_H_ 1346 | +#define NET_SSL_SGX_UTIL_H_ 1347 | + 1348 | +#include 1349 | +#include 1350 | + 1351 | +#include 1352 | + 1353 | +#include 1354 | + 1355 | +namespace net { 1356 | + 1357 | +class SGXEnclaveID { 1358 | + public: 1359 | + SGXEnclaveID(); 1360 | + ~SGXEnclaveID(); 1361 | + sgx_enclave_id_t eid() { return eid_; } 1362 | + private: 1363 | + sgx_enclave_id_t eid_; 1364 | +}; 1365 | + 1366 | +} // namespace net 1367 | + 1368 | +BIGNUM *LittleEndianArrayToBIGNUMuint8_t(uint8_t *arr, uint32_t arr_len); 1369 | + 1370 | +#endif // NET_SSL_SGX_UTIL_H_ 1371 | diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml 1372 | index 6e1cc97..d7a1799 100644 1373 | --- a/tools/metrics/histograms/histograms.xml 1374 | +++ b/tools/metrics/histograms/histograms.xml 1375 | @@ -8310,6 +8310,11 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. 1376 | Time spent generating a domain bound cert. 1377 | 1378 | 1379 | + 1380 | + ebp@chromium.org 1381 | + Time spent signing a TLS digest using a bound token. 1382 | + 1383 | + 1384 | 1385 | mattm@chromium.org 1386 | 1387 | @@ -58122,6 +58127,7 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. 1388 | 1389 | 1390 | 1391 | + 1392 | 1393 | 1394 | 1395 | @@ -71283,6 +71289,7 @@ To add a new entry, add it with any value and run test to compute valid value. 1396 | 1397 | 1398 | 1399 | + 1400 | 1401 | 1402 | 1403 | -- 1404 | 2.8.0.rc3.226.g39d4020 1405 | 1406 | --------------------------------------------------------------------------------