RT2680: Public EC key is shown as private
[openssl.git] / crypto / ec / ec_ameth.c
index a0ddb187a255c7e1049f22a1ebbc3240f68f01de..7fcc2c804327596278e84d08275309e35f1bdc13 100644 (file)
@@ -1,59 +1,10 @@
 /*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
- * 2006.
- */
-/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
+ * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
 #include <stdio.h>
@@ -61,9 +12,7 @@
 #include <openssl/x509.h>
 #include <openssl/ec.h>
 #include <openssl/bn.h>
-#ifndef OPENSSL_NO_CMS
-# include <openssl/cms.h>
-#endif
+#include <openssl/cms.h>
 #include <openssl/asn1t.h>
 #include "internal/asn1_int.h"
 #include "internal/evp_int.h"
@@ -343,7 +292,7 @@ static int ec_security_bits(const EVP_PKEY *pkey)
 
 static int ec_missing_parameters(const EVP_PKEY *pkey)
 {
-    if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
+    if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL)
         return 1;
     return 0;
 }
@@ -379,56 +328,40 @@ static void int_ec_free(EVP_PKEY *pkey)
     EC_KEY_free(pkey->pkey.ec);
 }
 
-static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
+typedef enum {
+    EC_KEY_PRINT_PRIVATE,
+    EC_KEY_PRINT_PUBLIC,
+    EC_KEY_PRINT_PARAM
+} ec_print_t;
+
+static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
 {
-    unsigned char *buffer = NULL;
     const char *ecstr;
-    size_t priv_len = 0, pub_len = 0, buf_len = 0;
-    int ret = 0, reason = ERR_R_BIO_LIB;
-    BIGNUM *pub_key = NULL;
-    BN_CTX *ctx = NULL;
+    unsigned char *priv = NULL, *pub = NULL;
+    size_t privlen = 0, publen = 0;
+    int ret = 0;
     const EC_GROUP *group;
-    const EC_POINT *public_key = NULL;
 
     if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
-        reason = ERR_R_PASSED_NULL_PARAMETER;
-        goto err;
-    }
-
-    if (ktype > 0) {
-        public_key = EC_KEY_get0_public_key(x);
-        if (public_key != NULL) {
-            pub_len = EC_POINT_point2oct(group, public_key,
-                                         EC_KEY_get_conv_form(x),
-                                         NULL, 0, NULL);
-            if (pub_len == 0) {
-                reason = ERR_R_EC_LIB;
-                goto err;
-            }
-            buf_len = pub_len;
-        }
+        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
     }
 
-    if (ktype == 2 && EC_KEY_get0_private_key(x) != NULL) {
-        priv_len = EC_KEY_priv2oct(x, NULL, 0);
-        if (priv_len == 0) {
-            reason = ERR_R_EC_LIB;
+    if (ktype != EC_KEY_PRINT_PARAM) {
+        publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
+        if (publen == 0)
             goto err;
-        }
-        if (priv_len > buf_len)
-            buf_len = priv_len;
     }
 
-    if (buf_len != 0) {
-        buffer = OPENSSL_malloc(buf_len);
-        if (buffer == NULL) {
-            reason = ERR_R_MALLOC_FAILURE;
+    if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
+        privlen = EC_KEY_priv2buf(x, &priv);
+        if (privlen == 0)
             goto err;
-        }
     }
-    if (ktype == 2)
+
+    if (ktype == EC_KEY_PRINT_PRIVATE)
         ecstr = "Private-Key";
-    else if (ktype == 1)
+    else if (ktype == EC_KEY_PRINT_PUBLIC)
         ecstr = "Public-Key";
     else
         ecstr = "ECDSA-Parameters";
@@ -439,23 +372,17 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
                    EC_GROUP_order_bits(group)) <= 0)
         goto err;
 
-    if (priv_len != 0) {
+    if (privlen != 0) {
         if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
             goto err;
-        if (EC_KEY_priv2oct(x, buffer, priv_len) == 0)
-            goto err;
-        if (ASN1_buf_print(bp, buffer, priv_len, off + 4) == 0)
+        if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
             goto err;
     }
 
-    if (pub_len != 0) {
+    if (publen != 0) {
         if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
             goto err;
-        if (EC_POINT_point2oct(group, public_key,
-                               EC_KEY_get_conv_form(x),
-                               buffer, pub_len, NULL) == 0)
-            goto err;
-        if (ASN1_buf_print(bp, buffer, pub_len, off + 4) == 0)
+        if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
             goto err;
     }
 
@@ -464,10 +391,9 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
     ret = 1;
  err:
     if (!ret)
-        ECerr(EC_F_DO_EC_KEY_PRINT, reason);
-    BN_free(pub_key);
-    BN_CTX_free(ctx);
-    OPENSSL_clear_free(buffer, buf_len);
+        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB);
+    OPENSSL_clear_free(priv, privlen);
+    OPENSSL_free(pub);
     return ret;
 }
 
@@ -492,19 +418,19 @@ static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
 static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
                              ASN1_PCTX *ctx)
 {
-    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM);
 }
 
 static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
                            ASN1_PCTX *ctx)
 {
-    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC);
 }
 
 static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
                             ASN1_PCTX *ctx)
 {
-    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE);
 }
 
 static int old_ec_priv_decode(EVP_PKEY *pkey,
@@ -617,6 +543,19 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
     old_ec_priv_encode
 };
 
+int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
+{
+    int private = EC_KEY_get0_private_key(x) != NULL;
+
+    return do_EC_KEY_print(bp, x, off,
+                private ? EC_KEY_PRINT_PUBLIC : EC_KEY_PRINT_PUBLIC);
+}
+
+int ECParameters_print(BIO *bp, const EC_KEY *x)
+{
+    return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
+}
+
 #ifndef OPENSSL_NO_CMS
 
 static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
@@ -842,7 +781,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
                         V_ASN1_UNDEF, NULL);
     }
 
-    /* See if custom paraneters set */
+    /* See if custom parameters set */
     kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
     if (kdf_type <= 0)
         goto err;
@@ -861,7 +800,7 @@ static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
         if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
             goto err;
     } else
-        /* Uknown KDF */
+        /* Unknown KDF */
         goto err;
     if (kdf_md == NULL) {
         /* Fixme later for better MD */