Skip to content

Commit

Permalink
Merge pull request dotnet/corefx#3812 from eerhardt/ShimBio2
Browse files Browse the repository at this point in the history
Shim Interop.Bignum and Interop.BIO methods.

Commit migrated from dotnet/corefx@aa215e4
  • Loading branch information
stephentoub committed Oct 13, 2015
2 parents 56b4033 + 275ec1d commit 9cc4ecb
Show file tree
Hide file tree
Showing 26 changed files with 277 additions and 132 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal static unsafe string DerStringToManagedString(byte[] derString)
byte[] utf8Bytes;

using (asn1String)
using (SafeBioHandle bio = libcrypto.BIO_new(libcrypto.BIO_s_mem()))
using (SafeBioHandle bio = CreateMemoryBio())
{
int len = Asn1StringPrintEx(bio, asn1String, Asn1StringPrintFlags.ASN1_STRFLGS_UTF8_CONVERT);

Expand All @@ -37,10 +37,10 @@ internal static unsafe string DerStringToManagedString(byte[] derString)
throw Crypto.CreateOpenSslCryptographicException();
}

int bioSize = libcrypto.GetMemoryBioSize(bio);
int bioSize = GetMemoryBioSize(bio);
utf8Bytes = new byte[bioSize + 1];

int read = libcrypto.BIO_read(bio, utf8Bytes, utf8Bytes.Length);
int read = BioRead(bio, utf8Bytes, utf8Bytes.Length);

if (read < 0)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative)]
internal static extern SafeBioHandle CreateMemoryBio();

[DllImport(Libraries.CryptoNative)]
internal static extern SafeBioHandle BioNewFile(string filename, string mode);

[DllImport(Libraries.CryptoNative)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool BioDestroy(IntPtr a);

[DllImport(Libraries.CryptoNative, CharSet = CharSet.Ansi)]
internal static extern int BioGets(SafeBioHandle b, [Out] StringBuilder buf, int size);

[DllImport(Libraries.CryptoNative)]
internal static extern int BioRead(SafeBioHandle b, byte[] data, int len);

[DllImport(Libraries.CryptoNative)]
internal static extern int BioWrite(SafeBioHandle b, byte[] data, int len);

[DllImport(Libraries.CryptoNative)]
internal static extern int GetMemoryBioSize(SafeBioHandle bio);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,23 @@

using System;
using System.Runtime.InteropServices;

using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class libcrypto
internal static partial class Crypto
{
[DllImport(Libraries.LibCrypto)]
internal static extern void BN_clear_free(IntPtr a);

[DllImport(Libraries.LibCrypto)]
private static extern IntPtr BN_bin2bn(byte[] s, int len, IntPtr zero);
[DllImport(Libraries.CryptoNative)]
internal static extern void BigNumDestroy(IntPtr a);

[DllImport(Libraries.LibCrypto)]
private static extern unsafe int BN_bn2bin(SafeBignumHandle a, byte* to);
[DllImport(Libraries.CryptoNative)]
private static extern IntPtr BigNumFromBinary(byte[] s, int len);

[DllImport(Libraries.LibCrypto)]
private static extern int BN_num_bits(SafeBignumHandle a);
[DllImport(Libraries.CryptoNative)]
private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte* to);

/// <summary>
/// Returns the number of bytes needed to export a BIGNUM.
/// </summary>
/// <remarks>This is a macro in bn.h, expanded here.</remarks>
private static int BN_num_bytes(SafeBignumHandle a)
{
return (BN_num_bits(a) + 7) / 8;
}
[DllImport(Libraries.CryptoNative)]
private static extern int GetBigNumBytes(SafeBignumHandle a);

internal static IntPtr CreateBignumPtr(byte[] bigEndianValue)
{
Expand All @@ -38,8 +28,7 @@ internal static IntPtr CreateBignumPtr(byte[] bigEndianValue)
return IntPtr.Zero;
}

IntPtr handle = BN_bin2bn(bigEndianValue, bigEndianValue.Length, IntPtr.Zero);
return handle;
return BigNumFromBinary(bigEndianValue, bigEndianValue.Length);
}

internal static SafeBignumHandle CreateBignum(byte[] bigEndianValue)
Expand All @@ -48,7 +37,7 @@ internal static SafeBignumHandle CreateBignum(byte[] bigEndianValue)
return new SafeBignumHandle(handle, true);
}

private static byte[] ExtractBignum(IntPtr bignum, int targetSize)
internal static byte[] ExtractBignum(IntPtr bignum, int targetSize)
{
// Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle
// to ensure that we don't destroy the key after extraction.
Expand All @@ -65,7 +54,7 @@ private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSi
return null;
}

int compactSize = BN_num_bytes(bignum);
int compactSize = GetBigNumBytes(bignum);

if (targetSize < compactSize)
{
Expand All @@ -85,7 +74,7 @@ private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSi
fixed (byte* to = buf)
{
byte* start = to + offset;
BN_bn2bin(bignum, start);
BigNumToBinary(bignum, start);
}

return buf;
Expand Down
50 changes: 0 additions & 50 deletions src/libraries/Common/src/Interop/Unix/libcrypto/Interop.BIO.cs

This file was deleted.

16 changes: 8 additions & 8 deletions src/libraries/Common/src/Interop/Unix/libcrypto/Interop.Rsa.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,18 @@ internal static unsafe RSAParameters ExportRsaParameters(SafeRsaHandle key, bool

rsaParameters = new RSAParameters
{
Modulus = ExtractBignum(rsaStructure->n, modulusSize),
Exponent = ExtractBignum(rsaStructure->e, 0),
Modulus = Crypto.ExtractBignum(rsaStructure->n, modulusSize),
Exponent = Crypto.ExtractBignum(rsaStructure->e, 0),
};

if (includePrivateParameters)
{
rsaParameters.D = ExtractBignum(rsaStructure->d, modulusSize);
rsaParameters.P = ExtractBignum(rsaStructure->p, halfModulus);
rsaParameters.DP = ExtractBignum(rsaStructure->dmp1, halfModulus);
rsaParameters.Q = ExtractBignum(rsaStructure->q, halfModulus);
rsaParameters.DQ = ExtractBignum(rsaStructure->dmq1, halfModulus);
rsaParameters.InverseQ = ExtractBignum(rsaStructure->iqmp, halfModulus);
rsaParameters.D = Crypto.ExtractBignum(rsaStructure->d, modulusSize);
rsaParameters.P = Crypto.ExtractBignum(rsaStructure->p, halfModulus);
rsaParameters.DP = Crypto.ExtractBignum(rsaStructure->dmp1, halfModulus);
rsaParameters.Q = Crypto.ExtractBignum(rsaStructure->q, halfModulus);
rsaParameters.DQ = Crypto.ExtractBignum(rsaStructure->dmq1, halfModulus);
rsaParameters.InverseQ = Crypto.ExtractBignum(rsaStructure->iqmp, halfModulus);
}
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,13 @@ public SafeBioHandle OutputBio

public static SafeSslHandle Create(SafeSslContextHandle context, bool isServer)
{
IntPtr memMethod = libcrypto.BIO_s_mem();

SafeBioHandle readBio = libcrypto.BIO_new(memMethod);
SafeBioHandle readBio = Crypto.CreateMemoryBio();
if (readBio.IsInvalid)
{
return new SafeSslHandle();
}

SafeBioHandle writeBio = libcrypto.BIO_new(memMethod);
SafeBioHandle writeBio = Crypto.CreateMemoryBio();
if (writeBio.IsInvalid)
{
readBio.Dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal SafeBignumHandle(IntPtr handle, bool ownsHandle)

protected override bool ReleaseHandle()
{
Interop.libcrypto.BN_clear_free(handle);
Interop.Crypto.BigNumDestroy(handle);
SetHandle(IntPtr.Zero);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ private SafeBioHandle() :

protected override bool ReleaseHandle()
{
Interop.libcrypto.BIO_free(handle);
Interop.Crypto.BioDestroy(handle);
SetHandle(IntPtr.Zero);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ set(NATIVECRYPTO_SOURCES
openssl.c
pal_asn1.cpp
pal_asn1_print.cpp
pal_bignum.cpp
pal_bio.cpp
pal_err.cpp
pal_evp.cpp
pal_evp_cipher.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal_bignum.h"

extern "C" void BigNumDestroy(BIGNUM* a)
{
if (a != nullptr)
{
BN_clear_free(a);
}
}

extern "C" BIGNUM* BigNumFromBinary(const unsigned char* s, int32_t len)
{
if (!s || !len)
{
return nullptr;
}

return BN_bin2bn(s, len, nullptr);
}

extern "C" int32_t BigNumToBinary(const BIGNUM* a, unsigned char* to)
{
if (!a || !to)
{
return 0;
}

return BN_bn2bin(a, to);
}

extern "C" int32_t GetBigNumBytes(const BIGNUM* a)
{
if (!a)
{
return 0;
}

return BN_num_bytes(a);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal_types.h"

#include <openssl/bn.h>

/*
Cleans up and deletes an BIGNUM instance.
Implemented by:
1) Calling BN_clear_free
No-op if a is null.
The given BIGNUM pointer is invalid after this call.
Always succeeds.
*/
extern "C" void BigNumDestroy(BIGNUM* a);

/*
Shims the BN_bin2bn method.
*/
extern "C" BIGNUM* BigNumFromBinary(const unsigned char* s, int32_t len);

/*
Shims the BN_bn2bin method.
*/
extern "C" int32_t BigNumToBinary(const BIGNUM* a, unsigned char* to);

/*
Returns the number of bytes needed to export a BIGNUM.
*/
extern "C" int32_t GetBigNumBytes(const BIGNUM* a);
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "pal_bio.h"

#include <assert.h>

extern "C" BIO* CreateMemoryBio()
{
return BIO_new(BIO_s_mem());
}

extern "C" BIO* BioNewFile(const char* filename, const char* mode)
{
return BIO_new_file(filename, mode);
}

extern "C" int32_t BioDestroy(BIO* a)
{
return BIO_free(a);
}

extern "C" int32_t BioGets(BIO* b, char* buf, int32_t size)
{
return BIO_gets(b, buf, size);
}

extern "C" int32_t BioRead(BIO* b, void* buf, int32_t len)
{
return BIO_read(b, buf, len);
}

extern "C" int32_t BioWrite(BIO* b, const void* buf, int32_t len)
{
return BIO_write(b, buf, len);
}

extern "C" int32_t GetMemoryBioSize(BIO* bio)
{
long ret = BIO_get_mem_data(bio, nullptr);

// BIO_get_mem_data returns the memory size, which will always be
// an int32.
assert(ret <= INT32_MAX);
return static_cast<int32_t>(ret);
}
Loading

0 comments on commit 9cc4ecb

Please sign in to comment.