Home | History | Annotate | Download | only in ssl
      1 /* Copyright (c) 2015, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #include <openssl/ssl.h>
     16 
     17 #include <assert.h>
     18 #include <string.h>
     19 
     20 #include <utility>
     21 
     22 #include <openssl/bn.h>
     23 #include <openssl/bytestring.h>
     24 #include <openssl/curve25519.h>
     25 #include <openssl/ec.h>
     26 #include <openssl/err.h>
     27 #include <openssl/hrss.h>
     28 #include <openssl/mem.h>
     29 #include <openssl/nid.h>
     30 #include <openssl/rand.h>
     31 
     32 #include "internal.h"
     33 #include "../crypto/internal.h"
     34 
     35 
     36 BSSL_NAMESPACE_BEGIN
     37 
     38 namespace {
     39 
     40 class ECKeyShare : public SSLKeyShare {
     41  public:
     42   ECKeyShare(int nid, uint16_t group_id) : nid_(nid), group_id_(group_id) {}
     43 
     44   uint16_t GroupID() const override { return group_id_; }
     45 
     46   bool Offer(CBB *out) override {
     47     assert(!private_key_);
     48     // Set up a shared |BN_CTX| for all operations.
     49     UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
     50     if (!bn_ctx) {
     51       return false;
     52     }
     53     BN_CTXScope scope(bn_ctx.get());
     54 
     55     // Generate a private key.
     56     UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid_));
     57     private_key_.reset(BN_new());
     58     if (!group || !private_key_ ||
     59         !BN_rand_range_ex(private_key_.get(), 1,
     60                           EC_GROUP_get0_order(group.get()))) {
     61       return false;
     62     }
     63 
     64     // Compute the corresponding public key and serialize it.
     65     UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
     66     if (!public_key ||
     67         !EC_POINT_mul(group.get(), public_key.get(), private_key_.get(), NULL,
     68                       NULL, bn_ctx.get()) ||
     69         !EC_POINT_point2cbb(out, group.get(), public_key.get(),
     70                             POINT_CONVERSION_UNCOMPRESSED, bn_ctx.get())) {
     71       return false;
     72     }
     73 
     74     return true;
     75   }
     76 
     77   bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
     78               Span<const uint8_t> peer_key) override {
     79     assert(private_key_);
     80     *out_alert = SSL_AD_INTERNAL_ERROR;
     81 
     82     // Set up a shared |BN_CTX| for all operations.
     83     UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
     84     if (!bn_ctx) {
     85       return false;
     86     }
     87     BN_CTXScope scope(bn_ctx.get());
     88 
     89     UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid_));
     90     if (!group) {
     91       return false;
     92     }
     93 
     94     UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
     95     UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
     96     BIGNUM *x = BN_CTX_get(bn_ctx.get());
     97     if (!peer_point || !result || !x) {
     98       return false;
     99     }
    100 
    101     if (peer_key.empty() || peer_key[0] != POINT_CONVERSION_UNCOMPRESSED ||
    102         !EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(),
    103                             peer_key.size(), bn_ctx.get())) {
    104       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
    105       *out_alert = SSL_AD_DECODE_ERROR;
    106       return false;
    107     }
    108 
    109     // Compute the x-coordinate of |peer_key| * |private_key_|.
    110     if (!EC_POINT_mul(group.get(), result.get(), NULL, peer_point.get(),
    111                       private_key_.get(), bn_ctx.get()) ||
    112         !EC_POINT_get_affine_coordinates_GFp(group.get(), result.get(), x, NULL,
    113                                              bn_ctx.get())) {
    114       return false;
    115     }
    116 
    117     // Encode the x-coordinate left-padded with zeros.
    118     Array<uint8_t> secret;
    119     if (!secret.Init((EC_GROUP_get_degree(group.get()) + 7) / 8) ||
    120         !BN_bn2bin_padded(secret.data(), secret.size(), x)) {
    121       return false;
    122     }
    123 
    124     *out_secret = std::move(secret);
    125     return true;
    126   }
    127 
    128   bool Serialize(CBB *out) override {
    129     assert(private_key_);
    130     CBB cbb;
    131     UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid_));
    132     // Padding is added to avoid leaking the length.
    133     size_t len = BN_num_bytes(EC_GROUP_get0_order(group.get()));
    134     if (!CBB_add_asn1_uint64(out, group_id_) ||
    135         !CBB_add_asn1(out, &cbb, CBS_ASN1_OCTETSTRING) ||
    136         !BN_bn2cbb_padded(&cbb, len, private_key_.get()) ||
    137         !CBB_flush(out)) {
    138       return false;
    139     }
    140     return true;
    141   }
    142 
    143   bool Deserialize(CBS *in) override {
    144     assert(!private_key_);
    145     CBS private_key;
    146     if (!CBS_get_asn1(in, &private_key, CBS_ASN1_OCTETSTRING)) {
    147       return false;
    148     }
    149     private_key_.reset(BN_bin2bn(CBS_data(&private_key),
    150                                  CBS_len(&private_key), nullptr));
    151     return private_key_ != nullptr;
    152   }
    153 
    154  private:
    155   UniquePtr<BIGNUM> private_key_;
    156   int nid_;
    157   uint16_t group_id_;
    158 };
    159 
    160 class X25519KeyShare : public SSLKeyShare {
    161  public:
    162   X25519KeyShare() {}
    163 
    164   uint16_t GroupID() const override { return SSL_CURVE_X25519; }
    165 
    166   bool Offer(CBB *out) override {
    167     uint8_t public_key[32];
    168     X25519_keypair(public_key, private_key_);
    169     return !!CBB_add_bytes(out, public_key, sizeof(public_key));
    170   }
    171 
    172   bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
    173               Span<const uint8_t> peer_key) override {
    174     *out_alert = SSL_AD_INTERNAL_ERROR;
    175 
    176     Array<uint8_t> secret;
    177     if (!secret.Init(32)) {
    178       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    179       return false;
    180     }
    181 
    182     if (peer_key.size() != 32 ||
    183         !X25519(secret.data(), private_key_, peer_key.data())) {
    184       *out_alert = SSL_AD_DECODE_ERROR;
    185       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
    186       return false;
    187     }
    188 
    189     *out_secret = std::move(secret);
    190     return true;
    191   }
    192 
    193   bool Serialize(CBB *out) override {
    194     return (CBB_add_asn1_uint64(out, GroupID()) &&
    195             CBB_add_asn1_octet_string(out, private_key_, sizeof(private_key_)));
    196   }
    197 
    198   bool Deserialize(CBS *in) override {
    199     CBS key;
    200     if (!CBS_get_asn1(in, &key, CBS_ASN1_OCTETSTRING) ||
    201         CBS_len(&key) != sizeof(private_key_) ||
    202         !CBS_copy_bytes(&key, private_key_, sizeof(private_key_))) {
    203       return false;
    204     }
    205     return true;
    206   }
    207 
    208  private:
    209   uint8_t private_key_[32];
    210 };
    211 
    212 class CECPQ2KeyShare : public SSLKeyShare {
    213  public:
    214   CECPQ2KeyShare() {}
    215 
    216   uint16_t GroupID() const override { return SSL_CURVE_CECPQ2; }
    217 
    218   bool Offer(CBB *out) override {
    219     uint8_t x25519_public_key[32];
    220     X25519_keypair(x25519_public_key, x25519_private_key_);
    221 
    222     uint8_t hrss_entropy[HRSS_GENERATE_KEY_BYTES];
    223     HRSS_public_key hrss_public_key;
    224     RAND_bytes(hrss_entropy, sizeof(hrss_entropy));
    225     HRSS_generate_key(&hrss_public_key, &hrss_private_key_, hrss_entropy);
    226 
    227     uint8_t hrss_public_key_bytes[HRSS_PUBLIC_KEY_BYTES];
    228     HRSS_marshal_public_key(hrss_public_key_bytes, &hrss_public_key);
    229 
    230     if (!CBB_add_bytes(out, x25519_public_key, sizeof(x25519_public_key)) ||
    231         !CBB_add_bytes(out, hrss_public_key_bytes,
    232                        sizeof(hrss_public_key_bytes))) {
    233       return false;
    234     }
    235 
    236     return true;
    237   }
    238 
    239   bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
    240               uint8_t *out_alert, Span<const uint8_t> peer_key) override {
    241     Array<uint8_t> secret;
    242     if (!secret.Init(32 + HRSS_KEY_BYTES)) {
    243       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    244       return false;
    245     }
    246 
    247     uint8_t x25519_public_key[32];
    248     X25519_keypair(x25519_public_key, x25519_private_key_);
    249 
    250     HRSS_public_key peer_public_key;
    251     if (peer_key.size() != 32 + HRSS_PUBLIC_KEY_BYTES ||
    252         !HRSS_parse_public_key(&peer_public_key, peer_key.data() + 32) ||
    253         !X25519(secret.data(), x25519_private_key_, peer_key.data())) {
    254       *out_alert = SSL_AD_DECODE_ERROR;
    255       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
    256       return false;
    257     }
    258 
    259     uint8_t ciphertext[HRSS_CIPHERTEXT_BYTES];
    260     uint8_t entropy[HRSS_ENCAP_BYTES];
    261     RAND_bytes(entropy, sizeof(entropy));
    262     HRSS_encap(ciphertext, secret.data() + 32, &peer_public_key, entropy);
    263 
    264     if (!CBB_add_bytes(out_public_key, x25519_public_key,
    265                        sizeof(x25519_public_key)) ||
    266         !CBB_add_bytes(out_public_key, ciphertext, sizeof(ciphertext))) {
    267       return false;
    268     }
    269 
    270     *out_secret = std::move(secret);
    271     return true;
    272   }
    273 
    274   bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
    275               Span<const uint8_t> peer_key) override {
    276     *out_alert = SSL_AD_INTERNAL_ERROR;
    277 
    278     Array<uint8_t> secret;
    279     if (!secret.Init(32 + HRSS_KEY_BYTES)) {
    280       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    281       return false;
    282     }
    283 
    284     if (peer_key.size() != 32 + HRSS_CIPHERTEXT_BYTES ||
    285         !X25519(secret.data(), x25519_private_key_, peer_key.data())) {
    286       *out_alert = SSL_AD_DECODE_ERROR;
    287       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
    288       return false;
    289     }
    290 
    291     HRSS_decap(secret.data() + 32, &hrss_private_key_, peer_key.data() + 32,
    292                peer_key.size() - 32);
    293 
    294     *out_secret = std::move(secret);
    295     return true;
    296   }
    297 
    298  private:
    299   uint8_t x25519_private_key_[32];
    300   HRSS_private_key hrss_private_key_;
    301 };
    302 
    303 CONSTEXPR_ARRAY NamedGroup kNamedGroups[] = {
    304     {NID_secp224r1, SSL_CURVE_SECP224R1, "P-224", "secp224r1"},
    305     {NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256", "prime256v1"},
    306     {NID_secp384r1, SSL_CURVE_SECP384R1, "P-384", "secp384r1"},
    307     {NID_secp521r1, SSL_CURVE_SECP521R1, "P-521", "secp521r1"},
    308     {NID_X25519, SSL_CURVE_X25519, "X25519", "x25519"},
    309     {NID_CECPQ2, SSL_CURVE_CECPQ2, "CECPQ2", "CECPQ2"},
    310 };
    311 
    312 }  // namespace
    313 
    314 Span<const NamedGroup> NamedGroups() {
    315   return MakeConstSpan(kNamedGroups, OPENSSL_ARRAY_SIZE(kNamedGroups));
    316 }
    317 
    318 UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
    319   switch (group_id) {
    320     case SSL_CURVE_SECP224R1:
    321       return UniquePtr<SSLKeyShare>(
    322           New<ECKeyShare>(NID_secp224r1, SSL_CURVE_SECP224R1));
    323     case SSL_CURVE_SECP256R1:
    324       return UniquePtr<SSLKeyShare>(
    325           New<ECKeyShare>(NID_X9_62_prime256v1, SSL_CURVE_SECP256R1));
    326     case SSL_CURVE_SECP384R1:
    327       return UniquePtr<SSLKeyShare>(
    328           New<ECKeyShare>(NID_secp384r1, SSL_CURVE_SECP384R1));
    329     case SSL_CURVE_SECP521R1:
    330       return UniquePtr<SSLKeyShare>(
    331           New<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1));
    332     case SSL_CURVE_X25519:
    333       return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
    334     case SSL_CURVE_CECPQ2:
    335       return UniquePtr<SSLKeyShare>(New<CECPQ2KeyShare>());
    336     default:
    337       return nullptr;
    338   }
    339 }
    340 
    341 UniquePtr<SSLKeyShare> SSLKeyShare::Create(CBS *in) {
    342   uint64_t group;
    343   if (!CBS_get_asn1_uint64(in, &group) || group > 0xffff) {
    344     return nullptr;
    345   }
    346   UniquePtr<SSLKeyShare> key_share = Create(static_cast<uint16_t>(group));
    347   if (!key_share || !key_share->Deserialize(in)) {
    348     return nullptr;
    349   }
    350   return key_share;
    351 }
    352 
    353 
    354 bool SSLKeyShare::Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
    355                          uint8_t *out_alert, Span<const uint8_t> peer_key) {
    356   *out_alert = SSL_AD_INTERNAL_ERROR;
    357   return Offer(out_public_key) &&
    358          Finish(out_secret, out_alert, peer_key);
    359 }
    360 
    361 bool ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
    362   for (const auto &group : kNamedGroups) {
    363     if (group.nid == nid) {
    364       *out_group_id = group.group_id;
    365       return true;
    366     }
    367   }
    368   return false;
    369 }
    370 
    371 bool ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
    372   for (const auto &group : kNamedGroups) {
    373     if (len == strlen(group.name) &&
    374         !strncmp(group.name, name, len)) {
    375       *out_group_id = group.group_id;
    376       return true;
    377     }
    378     if (len == strlen(group.alias) &&
    379         !strncmp(group.alias, name, len)) {
    380       *out_group_id = group.group_id;
    381       return true;
    382     }
    383   }
    384   return false;
    385 }
    386 
    387 BSSL_NAMESPACE_END
    388 
    389 using namespace bssl;
    390 
    391 const char* SSL_get_curve_name(uint16_t group_id) {
    392   for (const auto &group : kNamedGroups) {
    393     if (group.group_id == group_id) {
    394       return group.name;
    395     }
    396   }
    397   return nullptr;
    398 }
    399