sm2-ecdh revised
parent
6715f35753
commit
23c020e186
|
|
@ -23,7 +23,16 @@
|
|||
* secret from their private key and the peer's public key.
|
||||
*
|
||||
* This is plain ECDH on the SM2P256V1 curve, not the full SM2 key exchange
|
||||
* protocol from GB/T 32918.3. */
|
||||
* protocol from GB/T 32918.3.
|
||||
*
|
||||
* Roles in this example:
|
||||
* Alice: makes an SM2 key pair, sends her public key to Bob, and combines
|
||||
* her private key with Bob's public key.
|
||||
* Bob: does the same in the other direction.
|
||||
*
|
||||
* Only public keys are exchanged, so each side is given its own ecc_key for
|
||||
* the peer, imported from the bytes that crossed the wire. Both then arrive
|
||||
* at the same secret without it ever being transmitted. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
|
@ -33,9 +42,14 @@
|
|||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/sm2.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
|
||||
#ifdef WOLFSSL_SM2
|
||||
|
||||
#define SM2_FIELD_SZ 32 /* SM2P256V1: 256-bit curve */
|
||||
#define SM2_SECRET_SZ SM2_FIELD_SZ /* ECDH secret is one X ord */
|
||||
#define SM2_PUB_KEY_SZ (1 + SM2_FIELD_SZ * 2) /* X9.63 point: 04 || X || Y */
|
||||
|
||||
static void print_hex(const char* label, const byte* data, word32 len)
|
||||
{
|
||||
word32 i;
|
||||
|
|
@ -48,68 +62,148 @@ static void print_hex(const char* label, const byte* data, word32 len)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
WC_RNG rng;
|
||||
int rngInit = 0;
|
||||
ecc_key alice;
|
||||
ecc_key bob;
|
||||
int aliceInit = 0;
|
||||
int bobInit = 0;
|
||||
byte secretA[32];
|
||||
byte secretB[32];
|
||||
word32 secretASz = (word32)sizeof(secretA);
|
||||
word32 secretBSz = (word32)sizeof(secretB);
|
||||
int ret;
|
||||
|
||||
WC_RNG rng;
|
||||
int rngInit = 0;
|
||||
|
||||
/* Every struct below is declared before the first "goto exit" so that the
|
||||
* cleanup at the bottom always sees initialised members. */
|
||||
struct {
|
||||
byte publicKey[SM2_PUB_KEY_SZ]; /* only public data is sent */
|
||||
word32 publicKeySz;
|
||||
} Wire = {0};
|
||||
|
||||
struct {
|
||||
ecc_key key; /* Alice's own key pair */
|
||||
int keyInit;
|
||||
ecc_key peerKey; /* Alice view: Bob's pubkey */
|
||||
int peerKeyInit;
|
||||
byte sharedSecret[SM2_SECRET_SZ];
|
||||
word32 sharedSecretSz;
|
||||
} Alice = {0};
|
||||
|
||||
struct {
|
||||
ecc_key key; /* Bob's own key pair */
|
||||
int keyInit;
|
||||
ecc_key peerKey; /* Bob view: Alice's pubkey */
|
||||
int peerKeyInit;
|
||||
byte sharedSecret[SM2_SECRET_SZ];
|
||||
word32 sharedSecretSz;
|
||||
} Bob = {0};
|
||||
|
||||
/* --- Init Alice --- */
|
||||
ret = wc_ecc_init(&Alice.key);
|
||||
if (ret != 0) goto exit; else Alice.keyInit = 1;
|
||||
ret = wc_ecc_init(&Alice.peerKey);
|
||||
if (ret != 0) goto exit; else Alice.peerKeyInit = 1;
|
||||
Alice.sharedSecretSz = (word32)sizeof(Alice.sharedSecret);
|
||||
/* --- Init Alice --- */
|
||||
|
||||
/* --- Init Bob --- */
|
||||
ret = wc_ecc_init(&Bob.key);
|
||||
if (ret != 0) goto exit; else Bob.keyInit = 1;
|
||||
ret = wc_ecc_init(&Bob.peerKey);
|
||||
if (ret != 0) goto exit; else Bob.peerKeyInit = 1;
|
||||
Bob.sharedSecretSz = (word32)sizeof(Bob.sharedSecret);
|
||||
/* --- Init Bob --- */
|
||||
|
||||
/* --- One rng instance for simplicity -- */
|
||||
ret = wc_InitRng(&rng);
|
||||
if (ret != 0) {
|
||||
printf("wc_InitRng failed %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
rngInit = 1;
|
||||
/* --- One rng instance for simplicity -- */
|
||||
|
||||
ret = wc_ecc_init(&alice);
|
||||
if (ret != 0)
|
||||
goto exit;
|
||||
aliceInit = 1;
|
||||
ret = wc_ecc_init(&bob);
|
||||
if (ret != 0)
|
||||
goto exit;
|
||||
bobInit = 1;
|
||||
|
||||
ret = wc_ecc_sm2_make_key(&rng, &alice, WC_ECC_FLAG_NONE);
|
||||
/* --- Each side makes its own SM2 key pair --- */
|
||||
ret = wc_ecc_sm2_make_key(&rng, &Alice.key, WC_ECC_FLAG_NONE);
|
||||
if (ret == 0)
|
||||
ret = wc_ecc_sm2_make_key(&rng, &bob, WC_ECC_FLAG_NONE);
|
||||
ret = wc_ecc_sm2_make_key(&rng, &Bob.key, WC_ECC_FLAG_NONE);
|
||||
if (ret != 0) {
|
||||
printf("wc_ecc_sm2_make_key failed %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
printf("Generated two SM2 keys\n");
|
||||
/* --- Each side makes its own SM2 key pair --- */
|
||||
|
||||
#ifdef ECC_TIMING_RESISTANT
|
||||
/* Timing-resistant point math needs an RNG on the private key. */
|
||||
ret = wc_ecc_set_rng(&alice, &rng);
|
||||
/* --- Timing-resistant point math needs an RNG on the private key --- */
|
||||
ret = wc_ecc_set_rng(&Alice.key, &rng);
|
||||
if (ret == 0)
|
||||
ret = wc_ecc_set_rng(&bob, &rng);
|
||||
ret = wc_ecc_set_rng(&Bob.key, &rng);
|
||||
if (ret != 0) {
|
||||
printf("wc_ecc_set_rng failed %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
/* --- Timing-resistant point math needs an RNG on the private key --- */
|
||||
#endif
|
||||
|
||||
/* Each side uses its own private key and the peer's public key. */
|
||||
ret = wc_ecc_sm2_shared_secret(&alice, &bob, secretA, &secretASz);
|
||||
/* --- Alice sends her public key to Bob --- */
|
||||
{
|
||||
/* - Export Alice's public point (simulate sending pubkey only) - */
|
||||
Wire.publicKeySz = SM2_PUB_KEY_SZ;
|
||||
ret = wc_ecc_export_x963_ex(&Alice.key, Wire.publicKey,
|
||||
&Wire.publicKeySz, 0);
|
||||
if (ret != 0) {printf("Could not export Alice's pubkey\n"); goto exit;}
|
||||
/* - Export Alice's public point (simulate sending pubkey only) - */
|
||||
|
||||
/* - Bob saves the public key he received - */
|
||||
ret = wc_ecc_import_x963_ex(Wire.publicKey, Wire.publicKeySz,
|
||||
&Bob.peerKey, ECC_SM2P256V1);
|
||||
if (ret != 0) {
|
||||
printf("Bob could not import Alice's pubkey\n");
|
||||
goto exit;
|
||||
}
|
||||
/* - Bob saves the public key he received - */
|
||||
}
|
||||
/* --- Alice sends her public key to Bob --- */
|
||||
|
||||
/* --- Reset the wire for Bob's public key --- */
|
||||
memset(&Wire, 0, sizeof(Wire));
|
||||
/* --- Reset the wire for Bob's public key --- */
|
||||
|
||||
/* --- Bob sends his public key to Alice --- */
|
||||
{
|
||||
/* - Export Bob's public point (simulate sending pubkey only) - */
|
||||
Wire.publicKeySz = SM2_PUB_KEY_SZ;
|
||||
ret = wc_ecc_export_x963_ex(&Bob.key, Wire.publicKey,
|
||||
&Wire.publicKeySz, 0);
|
||||
if (ret != 0) {printf("Could not export Bob's pubkey\n"); goto exit;}
|
||||
/* - Export Bob's public point (simulate sending pubkey only) - */
|
||||
|
||||
/* - Alice saves the public key she received - */
|
||||
ret = wc_ecc_import_x963_ex(Wire.publicKey, Wire.publicKeySz,
|
||||
&Alice.peerKey, ECC_SM2P256V1);
|
||||
if (ret != 0) {
|
||||
printf("Alice could not import Bob's pubkey\n");
|
||||
goto exit;
|
||||
}
|
||||
/* - Alice saves the public key she received - */
|
||||
}
|
||||
/* --- Bob sends his public key to Alice --- */
|
||||
|
||||
/* --- Each side computes the shared secret --- */
|
||||
/* Own private key plus the peer's public key. The size in is the buffer
|
||||
* size available; on return it holds the secret length. */
|
||||
ret = wc_ecc_sm2_shared_secret(&Alice.key, &Alice.peerKey,
|
||||
Alice.sharedSecret, &Alice.sharedSecretSz);
|
||||
if (ret == 0)
|
||||
ret = wc_ecc_sm2_shared_secret(&bob, &alice, secretB, &secretBSz);
|
||||
ret = wc_ecc_sm2_shared_secret(&Bob.key, &Bob.peerKey,
|
||||
Bob.sharedSecret, &Bob.sharedSecretSz);
|
||||
if (ret != 0) {
|
||||
printf("wc_ecc_sm2_shared_secret failed %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
/* --- Each side computes the shared secret --- */
|
||||
|
||||
print_hex("alice secret", secretA, secretASz);
|
||||
print_hex("bob secret", secretB, secretBSz);
|
||||
print_hex("alice secret", Alice.sharedSecret, Alice.sharedSecretSz);
|
||||
print_hex("bob secret", Bob.sharedSecret, Bob.sharedSecretSz);
|
||||
|
||||
if (secretASz != secretBSz ||
|
||||
memcmp(secretA, secretB, secretASz) != 0) {
|
||||
if (Alice.sharedSecretSz != Bob.sharedSecretSz ||
|
||||
memcmp(Alice.sharedSecret, Bob.sharedSecret,
|
||||
Alice.sharedSecretSz) != 0) {
|
||||
printf("Shared secrets differ!\n");
|
||||
ret = -1;
|
||||
goto exit;
|
||||
|
|
@ -118,10 +212,19 @@ int main(void)
|
|||
ret = 0;
|
||||
|
||||
exit:
|
||||
if (bobInit)
|
||||
wc_ecc_free(&bob);
|
||||
if (aliceInit)
|
||||
wc_ecc_free(&alice);
|
||||
if (ret != 0)
|
||||
printf("error %d: %s\n", ret, wc_GetErrorString(ret));
|
||||
|
||||
if (Bob.peerKeyInit)
|
||||
wc_ecc_free(&Bob.peerKey);
|
||||
if (Bob.keyInit)
|
||||
wc_ecc_free(&Bob.key);
|
||||
|
||||
if (Alice.peerKeyInit)
|
||||
wc_ecc_free(&Alice.peerKey);
|
||||
if (Alice.keyInit)
|
||||
wc_ecc_free(&Alice.key);
|
||||
|
||||
if (rngInit)
|
||||
wc_FreeRng(&rng);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue