Skip to content

Commit

Permalink
Add print helper functions for RSA and DSA (#1354)
Browse files Browse the repository at this point in the history
* Add print helper functions for NTP:
* DSA_print
* DSA_print_fp
* RSA_print
* RSA_print_fp
  • Loading branch information
andrewhop authored Dec 15, 2023
1 parent 0e22b2e commit eee7576
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 0 deletions.
24 changes: 24 additions & 0 deletions crypto/dsa/dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@

#include <string.h>

#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/ex_data.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
Expand Down Expand Up @@ -125,6 +127,28 @@ void DSA_free(DSA *dsa) {
OPENSSL_free(dsa);
}

int DSA_print(BIO *bio, const DSA *dsa, int indent) {
EVP_PKEY *pkey = EVP_PKEY_new();
int ret = pkey != NULL &&
EVP_PKEY_set1_DSA(pkey, (DSA *)dsa) &&
EVP_PKEY_print_private(bio, pkey, indent, NULL);
EVP_PKEY_free(pkey);
return ret;
}


int DSA_print_fp(FILE *fp, const DSA *dsa, int indent) {
BIO *bio = BIO_new(BIO_s_file());
if (bio == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(bio, fp, BIO_NOCLOSE);
int ret = DSA_print(bio, dsa, indent);
BIO_free(bio);
return ret;
}

int DSA_up_ref(DSA *dsa) {
CRYPTO_refcount_inc(&dsa->references);
return 1;
Expand Down
53 changes: 53 additions & 0 deletions crypto/dsa/dsa_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,56 @@ s2lmkAIcLIFUDFrbC2nViaB5ATM9ARKk6F2QwnCfGCyZ6A==
EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), sig.data(),
sig.size(), dsa.get()));
}

TEST(DSATest, DSAPrint) {
bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
ASSERT_TRUE(dsa);
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));

DSA_print(bio.get(), dsa.get(), 4);
const uint8_t *data;
size_t len;
BIO_mem_contents(bio.get(), &data, &len);

const char *expected = ""
" Private-Key: (512 bit)\n"
" priv:\n"
" 20:70:b3:22:3d:ba:37:2f:de:1c:0f:fc:7b:2e:3b:\n"
" 49:8b:26:06:14\n"
" pub:\n"
" 19:13:18:71:d7:5b:16:12:a8:19:f2:9d:78:d1:b0:\n"
" d7:34:6f:7a:a7:7b:b6:2a:85:9b:fd:6c:56:75:da:\n"
" 9d:21:2d:3a:36:ef:16:72:ef:66:0b:8c:7c:25:5c:\n"
" c0:ec:74:85:8f:ba:33:f4:4c:06:69:96:30:a7:6b:\n"
" 03:0e:e3:33\n"
" P:\n"
" 00:8d:f2:a4:94:49:22:76:aa:3d:25:75:9b:b0:68:\n"
" 69:cb:ea:c0:d8:3a:fb:8d:0c:f7:cb:b8:32:4f:0d:\n"
" 78:82:e5:d0:76:2f:c5:b7:21:0e:af:c2:e9:ad:ac:\n"
" 32:ab:7a:ac:49:69:3d:fb:f8:37:24:c2:ec:07:36:\n"
" ee:31:c8:02:91\n"
" Q:\n"
" 00:c7:73:21:8c:73:7e:c8:ee:99:3b:4f:2d:ed:30:\n"
" f4:8e:da:ce:91:5f\n"
" G:\n"
" 62:6d:02:78:39:ea:0a:13:41:31:63:a5:5b:4c:b5:\n"
" 00:29:9d:55:22:95:6c:ef:cb:3b:ff:10:f3:99:ce:\n"
" 2c:2e:71:cb:9d:e5:fa:24:ba:bf:58:e5:b7:95:21:\n"
" 92:5c:9c:c4:2e:9f:6f:46:4b:08:8c:c5:72:af:53:\n"
" e6:d7:88:02\n";
ASSERT_EQ(Bytes(expected), Bytes(data, len));

#if !defined(OPENSSL_ANDROID)
// On Android, when running from an APK, |tmpfile| does not work. See
// b/36991167#comment8.
FILE *tmp = tmpfile();
ASSERT_TRUE(DSA_print_fp(tmp, dsa.get(), 4));
fseek(tmp, 0, SEEK_END);
long fileSize = ftell(tmp);
rewind(tmp);
std::unique_ptr<uint8_t[]> buf(new uint8_t[fileSize]);
size_t bytesRead = fread(buf.get(), 1, fileSize, tmp);
ASSERT_EQ(bytesRead, (size_t)fileSize);
ASSERT_EQ(Bytes(expected), Bytes(buf.get(), fileSize));
#endif
}
14 changes: 14 additions & 0 deletions crypto/rsa_extra/rsa_print.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <openssl/rsa.h>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>


Expand All @@ -20,3 +22,15 @@ int RSA_print(BIO *bio, const RSA *rsa, int indent) {
EVP_PKEY_free(pkey);
return ret;
}

int RSA_print_fp(FILE *fp, const RSA *rsa, int indent) {
BIO *bio = BIO_new(BIO_s_file());
if (bio == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fp(bio, fp, BIO_NOCLOSE);
int ret = RSA_print(bio, rsa, indent);
BIO_free(bio);
return ret;
}
65 changes: 65 additions & 0 deletions crypto/rsa_extra/rsa_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include <gtest/gtest.h>

#include <openssl/bn.h>
#include <openssl/bio.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
Expand Down Expand Up @@ -1392,6 +1393,70 @@ TEST(RSATest, OverwriteKey) {
check_rsa_compatible(/*enc=*/key2.get(), /*dec=*/key1.get()));
}

TEST(RSATest, PrintBio) {
bssl::UniquePtr<RSA> rsa(
RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
ASSERT_TRUE(rsa);
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));

RSA_print(bio.get(), rsa.get(), 4);
const uint8_t *data;
size_t len;
BIO_mem_contents(bio.get(), &data, &len);

const char *expected = ""
" Private-Key: (512 bit)\n"
" modulus:\n"
" 00:aa:36:ab:ce:88:ac:fd:ff:55:52:3c:7f:c4:52:\n"
" 3f:90:ef:a0:0d:f3:77:4a:25:9f:2e:62:b4:c5:d9:\n"
" 9c:b5:ad:b3:00:a0:28:5e:53:01:93:0e:0c:70:fb:\n"
" 68:76:93:9c:e6:16:ce:62:4a:11:e0:08:6d:34:1e:\n"
" bc:ac:a0:a1:f5\n"
" publicExponent: 17 (0x11)\n"
" privateExponent:\n"
" 0a:03:37:48:62:64:87:69:5f:5f:30:bc:38:b9:8b:\n"
" 44:c2:cd:2d:ff:43:40:98:cd:20:d8:a1:38:d0:90:\n"
" bf:64:79:7c:3f:a7:a2:cd:cb:3c:d1:e0:bd:ba:26:\n"
" 54:b4:f9:df:8e:8a:e5:9d:73:3d:9f:33:b3:01:62:\n"
" 4a:fd:1d:51\n"
" prime1:\n"
" 00:d8:40:b4:16:66:b4:2e:92:ea:0d:a3:b4:32:04:\n"
" b5:cf:ce:33:52:52:4d:04:16:a5:a4:41:e7:00:af:\n"
" 46:12:0d\n"
" prime2:\n"
" 00:c9:7f:b1:f0:27:f4:53:f6:34:12:33:ea:aa:d1:\n"
" d9:35:3f:6c:42:d0:88:66:b1:d0:5a:0f:20:35:02:\n"
" 8b:9d:89\n"
" exponent1:\n"
" 59:0b:95:72:a2:c2:a9:c4:06:05:9d:c2:ab:2f:1d:\n"
" af:eb:7e:8b:4f:10:a7:54:9e:8e:ed:f5:b4:fc:e0:\n"
" 9e:05\n"
" exponent2:\n"
" 00:8e:3c:05:21:fe:15:e0:ea:06:a3:6f:f0:f1:0c:\n"
" 99:52:c3:5b:7a:75:14:fd:32:38:b8:0a:ad:52:98:\n"
" 62:8d:51\n"
" coefficient:\n"
" 36:3f:f7:18:9d:a8:e9:0b:1d:34:1f:71:d0:9b:76:\n"
" a8:a9:43:e1:1d:10:b2:4d:24:9f:2d:ea:fe:f8:0c:\n"
" 18:26\n";

ASSERT_EQ(Bytes(expected), Bytes(data, len));

#if !defined(OPENSSL_ANDROID)
// On Android, when running from an APK, |tmpfile| does not work. See
// b/36991167#comment8.
FILE *tmp = tmpfile();
ASSERT_TRUE(RSA_print_fp(tmp, rsa.get(), 4));
fseek(tmp, 0, SEEK_END);
long fileSize = ftell(tmp);
rewind(tmp);
std::unique_ptr<uint8_t[]> buf(new uint8_t[fileSize]);
size_t bytesRead = fread(buf.get(), 1, fileSize, tmp);
ASSERT_EQ(bytesRead, (size_t)fileSize);
ASSERT_EQ(Bytes(expected), Bytes(buf.get(), fileSize));
#endif
}

#if !defined(BORINGSSL_SHARED_LIBRARY)
TEST(RSATest, SqrtTwo) {
bssl::UniquePtr<BIGNUM> sqrt(BN_new()), pow2(BN_new());
Expand Down
9 changes: 9 additions & 0 deletions include/openssl/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@
#define OPENSSL_HEADER_DSA_H

#include <openssl/base.h>
#include <openssl/crypto.h>

#include <openssl/ex_data.h>
#include <stdio.h>

#if defined(__cplusplus)
extern "C" {
Expand All @@ -89,6 +91,13 @@ OPENSSL_EXPORT void DSA_free(DSA *dsa);
// DSA_up_ref increments the reference count of |dsa| and returns one.
OPENSSL_EXPORT int DSA_up_ref(DSA *dsa);

// DSA_print prints a textual representation of |dsa| to |bio|. It returns one
// on success or zero otherwise.
OPENSSL_EXPORT int DSA_print(BIO *bio, const DSA *dsa, int indent);

// DSA_print_fp prints a textual representation of |dsa| to |fp|. It returns one
// on success or zero otherwise.
OPENSSL_EXPORT int DSA_print_fp(FILE *fp, const DSA *dsa, int indent);

// Properties.

Expand Down
6 changes: 6 additions & 0 deletions include/openssl/rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@
#define OPENSSL_HEADER_RSA_H

#include <openssl/base.h>
#include <openssl/crypto.h>

#include <openssl/engine.h>
#include <openssl/ex_data.h>
#include <openssl/thread.h>
#include <stdio.h>

#if defined(__cplusplus)
extern "C" {
Expand Down Expand Up @@ -694,6 +696,10 @@ OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len,
// on success or zero otherwise.
OPENSSL_EXPORT int RSA_print(BIO *bio, const RSA *rsa, int indent);

// RSA_print_fp prints a textual representation of |rsa| to |fp|. It returns one
// on success or zero otherwise.
OPENSSL_EXPORT int RSA_print_fp(FILE *fp, const RSA *rsa, int indent);

// RSA_get0_pss_params returns NULL. In OpenSSL, this function retries RSA-PSS
// parameters associated with |RSA| objects, but BoringSSL does not support
// the id-RSASSA-PSS key encoding.
Expand Down

0 comments on commit eee7576

Please sign in to comment.