Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
elliptic_r1.cpp
Go to the documentation of this file.
2
5
6#include <fc/fwd_impl.hpp>
8#include <fc/log/logger.hpp>
9
10namespace fc { namespace crypto { namespace r1 {
11 namespace detail
12 {
14 {
15 public:
16 public_key_impl() : _key(nullptr) {}
17
19 {
20 if( _key != nullptr )
21 {
22 EC_KEY_free(_key);
23 }
24 }
26 {
27 _key = cpy._key ? EC_KEY_dup( cpy._key ) : nullptr;
28 }
29 EC_KEY* _key;
30 };
32 {
33 public:
34 private_key_impl() : _key(nullptr) {}
35
37 {
38 if( _key != nullptr )
39 {
40 EC_KEY_free(_key);
41 }
42 }
44 {
45 _key = cpy._key ? EC_KEY_dup( cpy._key ) : nullptr;
46 }
47 EC_KEY* _key;
48 };
49 }
50 static void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen)
51 {
52 if (*olen < SHA512_DIGEST_LENGTH) {
53 return NULL;
54 }
55 *olen = SHA512_DIGEST_LENGTH;
56 return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output);
57 }
58
59 // Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
60 // recid selects which key is recovered
61 // if check is non-zero, additional checks are performed
62 int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
63 {
64 if (!eckey) FC_THROW_EXCEPTION( exception, "null key" );
65
66 int ret = 0;
67 BN_CTX *ctx = NULL;
68
69 BIGNUM *x = NULL;
70 BIGNUM *e = NULL;
71 BIGNUM *order = NULL;
72 BIGNUM *sor = NULL;
73 BIGNUM *eor = NULL;
74 BIGNUM *field = NULL;
75 EC_POINT *R = NULL;
76 EC_POINT *O = NULL;
77 EC_POINT *Q = NULL;
78 BIGNUM *rr = NULL;
79 BIGNUM *zero = NULL;
80 int n = 0;
81 int i = recid / 2;
82
83 const BIGNUM *r, *s;
84 ECDSA_SIG_get0(ecsig, &r, &s);
85
86 const EC_GROUP *group = EC_KEY_get0_group(eckey);
87 if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
88 BN_CTX_start(ctx);
89 order = BN_CTX_get(ctx);
90 if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
91 x = BN_CTX_get(ctx);
92 if (!BN_copy(x, order)) { ret=-1; goto err; }
93 if (!BN_mul_word(x, i)) { ret=-1; goto err; }
94 if (!BN_add(x, x, r)) { ret=-1; goto err; }
95 field = BN_CTX_get(ctx);
96 if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
97 if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
98 if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
99 if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
100 if (check)
101 {
102 if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
103 if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
104 if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
105 }
106 if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
107 n = EC_GROUP_get_degree(group);
108 e = BN_CTX_get(ctx);
109 if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
110 if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
111 zero = BN_CTX_get(ctx);
112 BN_zero(zero);
113 if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
114 rr = BN_CTX_get(ctx);
115 if (!BN_mod_inverse(rr, r, order, ctx)) { ret=-1; goto err; }
116 sor = BN_CTX_get(ctx);
117 if (!BN_mod_mul(sor, s, rr, order, ctx)) { ret=-1; goto err; }
118 eor = BN_CTX_get(ctx);
119 if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
120 if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
121 if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
122
123 ret = 1;
124
125 err:
126 if (ctx) {
127 BN_CTX_end(ctx);
128 BN_CTX_free(ctx);
129 }
130 if (R != NULL) EC_POINT_free(R);
131 if (O != NULL) EC_POINT_free(O);
132 if (Q != NULL) EC_POINT_free(Q);
133 return ret;
134 }
135
136 compact_signature signature_from_ecdsa(const EC_KEY* key, const public_key_data& pub_data, fc::ecdsa_sig& sig, const fc::sha256& d) {
137 //We can't use ssl_bignum here; _get0() does not transfer ownership to us; _set0() does transfer ownership to fc::ecdsa_sig
138 const BIGNUM *sig_r, *sig_s;
139 BIGNUM *r = BN_new(), *s = BN_new();
140 ECDSA_SIG_get0(sig, &sig_r, &sig_s);
141 BN_copy(r, sig_r);
142 BN_copy(s, sig_s);
143
144 //want to always use the low S value
145 const EC_GROUP* group = EC_KEY_get0_group(key);
146 ssl_bignum order, halforder;
147 EC_GROUP_get_order(group, order, nullptr);
148 BN_rshift1(halforder, order);
149 if(BN_cmp(s, halforder) > 0)
150 BN_sub(s, order, s);
151
153
154 int nBitsR = BN_num_bits(r);
155 int nBitsS = BN_num_bits(s);
156 if(nBitsR > 256 || nBitsS > 256)
157 FC_THROW_EXCEPTION( exception, "Unable to sign" );
158
159 ECDSA_SIG_set0(sig, r, s);
160
161 int nRecId = -1;
162 for (int i=0; i<4; i++)
163 {
164 public_key keyRec;
165 keyRec.my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
166 if (ECDSA_SIG_recover_key_GFp(keyRec.my->_key, sig, (unsigned char*)&d, sizeof(d), i, 1) == 1)
167 {
168 if (keyRec.serialize() == pub_data )
169 {
170 nRecId = i;
171 break;
172 }
173 }
174 }
175 if (nRecId == -1)
176 FC_THROW_EXCEPTION( exception, "unable to construct recoverable key");
177
178 csig.data[0] = nRecId+27+4;
179 BN_bn2bin(r,&csig.data[33-(nBitsR+7)/8]);
180 BN_bn2bin(s,&csig.data[65-(nBitsS+7)/8]);
181
182 return csig;
183 }
184
185 int static inline EC_KEY_regenerate_key(EC_KEY *eckey, const BIGNUM *priv_key)
186 {
187 int ok = 0;
188 BN_CTX *ctx = NULL;
189 EC_POINT *pub_key = NULL;
190
191 if (!eckey) return 0;
192
193 const EC_GROUP *group = EC_KEY_get0_group(eckey);
194
195 if ((ctx = BN_CTX_new()) == NULL)
196 goto err;
197
198 pub_key = EC_POINT_new(group);
199
200 if (pub_key == NULL)
201 goto err;
202
203 if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
204 goto err;
205
206 EC_KEY_set_private_key(eckey,priv_key);
207 EC_KEY_set_public_key(eckey,pub_key);
208
209 ok = 1;
210
211 err:
212
213 if (pub_key) EC_POINT_free(pub_key);
214 if (ctx != NULL) BN_CTX_free(ctx);
215
216 return(ok);
217 }
218
219/*
220 public_key::public_key()
221 :my( new detail::public_key_impl() )
222 {
223 }
224
225 public_key::public_key( fc::bigint pub_x, fc::bigint pub_y )
226 :my( new detail::public_key_impl() )
227 {
228 }
229
230 public_key::~public_key()
231 {
232 }
233 */
234
236 {
237 // get point from this public key
238 const EC_POINT* master_pub = EC_KEY_get0_public_key( my->_key );
239 ec_group group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
240
241 ssl_bignum z;
242 BN_bin2bn((unsigned char*)&digest, sizeof(digest), z);
243
244 // multiply by digest
246 BN_one(one);
247 bn_ctx ctx(BN_CTX_new());
248
249 ec_point result(EC_POINT_new(group));
250 EC_POINT_mul(group, result, z, master_pub, one, ctx);
251
252 public_key rtn;
253 rtn.my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
254 EC_KEY_set_public_key(rtn.my->_key,result);
255
256 return rtn;
257 }
259 {
260 return my->_key != nullptr;
261 }
263 {
264 try {
265 ec_group group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
266 bn_ctx ctx(BN_CTX_new());
267
268 fc::bigint digest_bi( (char*)&digest, sizeof(digest) );
269
270 ssl_bignum order;
271 EC_GROUP_get_order(group, order, ctx);
272 if( digest_bi > fc::bigint(order) )
273 {
274 FC_THROW_EXCEPTION( exception, "digest > group order" );
275 }
276
277
279 const EC_POINT* digest_point = EC_KEY_get0_public_key( digest_key.my->_key );
280
281 // get point from this public key
282 const EC_POINT* master_pub = EC_KEY_get0_public_key( my->_key );
283
284 ssl_bignum z;
285 BN_bin2bn((unsigned char*)&digest, sizeof(digest), z);
286
287 // multiply by digest
289 BN_one(one);
290
291 ec_point result(EC_POINT_new(group));
292 EC_POINT_add(group, result, digest_point, master_pub, ctx);
293
294 if (EC_POINT_is_at_infinity(group, result))
295 {
296 FC_THROW_EXCEPTION( exception, "point at infinity" );
297 }
298
299
300 public_key rtn;
301 rtn.my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
302 EC_KEY_set_public_key(rtn.my->_key,result);
303 return rtn;
304 } FC_RETHROW_EXCEPTIONS( debug, "digest: ${digest}", ("digest",digest) );
305 }
306
307 std::string public_key::to_base58() const
308 {
310 uint32_t check = (uint32_t)sha256::hash(key.data, sizeof(key))._hash[0];
311 static_assert(sizeof(key) + sizeof(check) == 37, ""); // hack around gcc bug: key.size() should be constexpr, but isn't
312 array<char, 37> data;
313 memcpy(data.data, key.begin(), key.size());
314 memcpy(data.begin() + key.size(), (const char*)&check, sizeof(check));
315 return fc::to_base58(data.begin(), data.size(), fc::yield_function_t());
316 }
317
318 public_key public_key::from_base58( const std::string& b58 )
319 {
320 array<char, 37> data;
321 size_t s = fc::from_base58(b58, (char*)&data, sizeof(data) );
322 FC_ASSERT( s == sizeof(data) );
323
325 uint32_t check = (uint32_t)sha256::hash(data.data, sizeof(key))._hash[0];
326 FC_ASSERT( memcmp( (char*)&check, data.data + sizeof(key), sizeof(check) ) == 0 );
327 memcpy( (char*)key.data, data.data, sizeof(key) );
328 return public_key(key);
329 }
330
333
335 {
336 ssl_bignum z;
337 BN_bin2bn((unsigned char*)&offset, sizeof(offset), z);
338
339 ec_group group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
340 bn_ctx ctx(BN_CTX_new());
341 ssl_bignum order;
342 EC_GROUP_get_order(group, order, ctx);
343
344 // secexp = (seed + z) % order
345 ssl_bignum secexp;
346 BN_bin2bn((unsigned char*)&seed, sizeof(seed), secexp);
347 BN_add(secexp, secexp, z);
348 BN_mod(secexp, secexp, order, ctx);
349
350 fc::sha256 secret;
351 FC_ASSERT(BN_num_bytes(secexp) <= int64_t(sizeof(secret)));
352 auto shift = sizeof(secret) - BN_num_bytes(secexp);
353 BN_bn2bin(secexp, ((unsigned char*)&secret)+shift);
354 return regenerate( secret );
355 }
356
358 {
359 private_key self;
360 self.my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
361 if( !self.my->_key ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
362
364 BN_bin2bn( (const unsigned char*)&secret, 32, bn );
365
366 if( !EC_KEY_regenerate_key(self.my->_key,bn) )
367 {
368 FC_THROW_EXCEPTION( exception, "unable to regenerate key" );
369 }
370 return self;
371 }
372
374 {
375 if( !my->_key )
376 {
377 return fc::sha256();
378 }
379
380 fc::sha256 sec;
381 const BIGNUM* bn = EC_KEY_get0_private_key(my->_key);
382 if( bn == NULL )
383 {
384 FC_THROW_EXCEPTION( exception, "get private key failed" );
385 }
386 int nbytes = BN_num_bytes(bn);
387 BN_bn2bin(bn, &((unsigned char*)&sec)[32-nbytes] );
388 return sec;
389 }
390
392 {
393 private_key self;
394 EC_KEY* k = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
395 if( !k ) FC_THROW_EXCEPTION( exception, "Unable to generate EC key" );
396 self.my->_key = k;
397 if( !EC_KEY_generate_key( self.my->_key ) )
398 {
399 FC_THROW_EXCEPTION( exception, "ecc key generation error" );
400
401 }
402
403#if 0
404 = bigint( EC_KEY_get0_private_key( k );
405 EC_POINT* pub = EC_KEY_get0_public_key( k );
406 EC_GROUP* group = EC_KEY_get0_group( k );
407
408 EC_POINT_get_affine_coordinates_GFp( group, pub, self.my->_pub_x.get(), self.my->_pub_y.get(), nullptr/*ctx*/ );
409
410 EC_KEY_free(k);
411#endif
412
413 return self;
414 }
415
417 {
418 unsigned int buf_len = ECDSA_size(my->_key);
419// fprintf( stderr, "%d %d\n", buf_len, sizeof(sha256) );
420 signature sig;
421 FC_ASSERT( buf_len == sizeof(sig) );
422
423 if( !ECDSA_sign( 0,
424 (const unsigned char*)&digest, sizeof(digest),
425 (unsigned char*)&sig, &buf_len, my->_key ) )
426 {
427 FC_THROW_EXCEPTION( exception, "signing error" );
428 }
429
430
431 return sig;
432 }
434 {
435 return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key );
436 }
437
439 {
440 public_key_data dat;
441 if( !my->_key ) return dat;
442 EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED );
443 /*size_t nbytes = i2o_ECPublicKey( my->_key, nullptr ); */
444 /*FC_ASSERT( nbytes == 33 )*/
445 char* front = &dat.data[0];
446 i2o_ECPublicKey( my->_key, (unsigned char**)&front );
447 return dat;
448 /*
449 EC_POINT* pub = EC_KEY_get0_public_key( my->_key );
450 EC_GROUP* group = EC_KEY_get0_group( my->_key );
451 EC_POINT_get_affine_coordinates_GFp( group, pub, self.my->_pub_x.get(), self.my->_pub_y.get(), nullptr );
452 */
453 }
454
462 {
463 const char* front = &dat.data[0];
464 if( *front == 0 ){}
465 else
466 {
467 my->_key = o2i_ECPublicKey( &my->_key, (const unsigned char**)&front, sizeof(dat) );
468 if( !my->_key )
469 {
470 FC_THROW_EXCEPTION( exception, "error decoding public key", ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
471 }
472 }
473 }
475 {
476 const char* front = &dat.data[0];
477 if( *front == 0 ){}
478 else
479 {
480 my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
481 my->_key = o2i_ECPublicKey( &my->_key, (const unsigned char**)&front, sizeof(public_key_data) );
482 if( !my->_key )
483 {
484 FC_THROW_EXCEPTION( exception, "error decoding public key", ("s", ERR_error_string( ERR_get_error(), nullptr) ) );
485 }
486 }
487 }
488
490 {
491 return 1 == ECDSA_verify( 0, (unsigned char*)&digest, sizeof(digest), (unsigned char*)&sig, sizeof(sig), my->_key );
492 }
493
495 {
497 pub.my->_key = EC_KEY_new_by_curve_name( NID_X9_62_prime256v1 );
498 EC_KEY_set_public_key( pub.my->_key, EC_KEY_get0_public_key( my->_key ) );
499 return pub;
500 }
501
502
504 {
505 FC_ASSERT( my->_key != nullptr );
506 FC_ASSERT( other.my->_key != nullptr );
508 ECDH_compute_key( (unsigned char*)&buf, sizeof(buf), EC_KEY_get0_public_key(other.my->_key), my->_key, ecies_key_derivation );
509 return buf;
510 }
511
515
516 public_key::public_key( const compact_signature& c, const fc::sha256& digest, bool check_canonical )
517 {
518 int nV = c.data[0];
519 if (nV<27 || nV>=35)
520 FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
521
522 ecdsa_sig sig = ECDSA_SIG_new();
523 BIGNUM *r = BN_new(), *s = BN_new();
524 BN_bin2bn(&c.data[1],32,r);
525 BN_bin2bn(&c.data[33],32,s);
526 ECDSA_SIG_set0(sig, r, s);
527
528 my->_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
529
530 const EC_GROUP* group = EC_KEY_get0_group(my->_key);
531 ssl_bignum order, halforder;
532 EC_GROUP_get_order(group, order, nullptr);
533 BN_rshift1(halforder, order);
534 if(BN_cmp(s, halforder) > 0)
535 FC_THROW_EXCEPTION( exception, "invalid high s-value encountered in r1 signature" );
536
537 if (nV >= 31)
538 {
539 EC_KEY_set_conv_form( my->_key, POINT_CONVERSION_COMPRESSED );
540 nV -= 4;
541// fprintf( stderr, "compressed\n" );
542 }
543
544 if (ECDSA_SIG_recover_key_GFp(my->_key, sig, (unsigned char*)&digest, sizeof(digest), nV - 27, 0) == 1)
545 return;
546 FC_THROW_EXCEPTION( exception, "unable to reconstruct public key from signature" );
547 }
548
550 {
551 try {
552 FC_ASSERT( my->_key != nullptr );
553 auto my_pub_key = get_public_key().serialize(); // just for good measure
554 ecdsa_sig sig = ECDSA_do_sign((unsigned char*)&digest, sizeof(digest), my->_key);
555
556 if (sig==nullptr)
557 FC_THROW_EXCEPTION( exception, "Unable to sign" );
558
559 return signature_from_ecdsa(my->_key, my_pub_key, sig, digest);
560 } FC_RETHROW_EXCEPTIONS( warn, "sign ${digest}", ("digest", digest)("private_key",*this) );
561 }
562
564 {
565 if( my->_key )
566 {
567 EC_KEY_free(my->_key);
568 }
569 my->_key = pk.my->_key;
570 pk.my->_key = nullptr;
571 return *this;
572 }
574 :my(pk.my)
575 {
576 }
578 :my( fc::move( pk.my) )
579 {
580 }
582 :my(pk.my)
583 {
584 }
586 :my( fc::move( pk.my) )
587 {
588 }
589
591 {
592 if( my->_key )
593 {
594 EC_KEY_free(my->_key);
595 }
596 my->_key = pk.my->_key;
597 pk.my->_key = nullptr;
598 return *this;
599 }
601 {
602 if( my->_key )
603 {
604 EC_KEY_free(my->_key);
605 }
606 my->_key = EC_KEY_dup(pk.my->_key);
607 return *this;
608 }
610 {
611 if( my->_key )
612 {
613 EC_KEY_free(my->_key);
614 }
615 my->_key = EC_KEY_dup(pk.my->_key);
616 return *this;
617 }
618
619}
620}
622 {
623 vo = var.get_secret();
624 }
626 {
627 fc::sha256 sec;
628 from_variant( var, sec );
630 }
631
633 {
634 vo = var.serialize();
635 }
637 {
639 from_variant( var, dat );
640 vo = crypto::r1::public_key(dat);
641 }
642
643
644}
std::string one()
const mie::Vuint & r
Definition bn.cpp:28
T data[N]
Definition array.hpp:37
private_key_impl(const private_key_impl &cpy)
public_key_impl(const public_key_impl &cpy)
an elliptic curve private key.
bool verify(const fc::sha256 &digest, const signature &sig)
signature sign(const fc::sha256 &digest) const
static private_key generate_from_seed(const fc::sha256 &seed, const fc::sha256 &offset=fc::sha256())
private_key_secret get_secret() const
public_key get_public_key() const
fc::sha512 get_shared_secret(const public_key &pub) const
compact_signature sign_compact(const fc::sha256 &digest) const
static private_key regenerate(const fc::sha256 &secret)
static private_key generate()
private_key & operator=(private_key &&pk)
contains only the public point of an elliptic curve key.
public_key & operator=(public_key &&pk)
bool verify(const fc::sha256 &digest, const signature &sig)
public_key add(const fc::sha256 &offset) const
static public_key from_base58(const std::string &b58)
public_key_data serialize() const
std::string to_base58() const
Allows to convert current public key object into base58 number.
public_key mult(const fc::sha256 &offset)
static sha256 hash(const char *d, uint32_t dlen)
Definition sha256.cpp:44
uint64_t _hash[4]
Definition sha256.hpp:100
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
Definition variant.hpp:191
bool debug
Defines exception's used by fc.
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
ehm field
bignum_st BIGNUM
Definition bigint.hpp:7
Definition bn.h:56
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
compact_signature signature_from_ecdsa(const EC_KEY *key, const public_key_data &pub, fc::ecdsa_sig &sig, const fc::sha256 &d)
namespace sysio::chain
Definition authority.cpp:3
std::string to_base58(const char *d, size_t s, const fc::yield_function_t &yield)
Definition base58.cpp:618
fc::sha256 digest(const T &value)
Definition digest.hpp:9
std::vector< char > from_base58(const std::string &base58_str)
Definition base58.cpp:628
void from_variant(const fc::variant &v, sysio::chain::chain_id_type &cid)
void to_variant(const sysio::chain::shared_public_key &var, fc::variant &vo)
Definition authority.cpp:4
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
#define R
uint8_t key[16]
Definition yubico_otp.c:41
CK_ULONG d
bool pub
CK_RV ret
char * s
uint8_t buf[2048]
memcpy((char *) pInfo->slotDescription, s, l)