@@ -128,6 +128,11 @@ DataPointer::~DataPointer() {
128
128
reset ();
129
129
}
130
130
131
+ void DataPointer::zero () {
132
+ if (!data_) return ;
133
+ OPENSSL_cleanse (data_, len_);
134
+ }
135
+
131
136
void DataPointer::reset (void * data, size_t length) {
132
137
if (data_ != nullptr ) {
133
138
OPENSSL_clear_free (data_, len_);
@@ -1160,6 +1165,52 @@ Result<X509Pointer, int> X509Pointer::Parse(
1160
1165
return Result<X509Pointer, int >(ERR_get_error ());
1161
1166
}
1162
1167
1168
+ bool X509View::enumUsages (UsageCallback callback) const {
1169
+ if (cert_ == nullptr ) return false ;
1170
+ StackOfASN1 eku (static_cast <STACK_OF (ASN1_OBJECT)*>(
1171
+ X509_get_ext_d2i (cert_, NID_ext_key_usage, nullptr , nullptr )));
1172
+ if (!eku) return false ;
1173
+ const int count = sk_ASN1_OBJECT_num (eku.get ());
1174
+ char buf[256 ]{};
1175
+
1176
+ int j = 0 ;
1177
+ for (int i = 0 ; i < count; i++) {
1178
+ if (OBJ_obj2txt (buf, sizeof (buf), sk_ASN1_OBJECT_value (eku.get (), i), 1 ) >=
1179
+ 0 ) {
1180
+ callback (buf);
1181
+ }
1182
+ }
1183
+ return true ;
1184
+ }
1185
+
1186
+ bool X509View::ifRsa (KeyCallback<Rsa> callback) const {
1187
+ if (cert_ == nullptr ) return true ;
1188
+ OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey (cert_);
1189
+ OSSL3_CONST RSA* rsa = nullptr ;
1190
+ auto id = EVP_PKEY_id (pkey);
1191
+ if (id == EVP_PKEY_RSA || id == EVP_PKEY_RSA2 || id == EVP_PKEY_RSA_PSS) {
1192
+ Rsa rsa (EVP_PKEY_get0_RSA (pkey));
1193
+ if (!rsa) [[unlikely]]
1194
+ return true ;
1195
+ return callback (rsa);
1196
+ }
1197
+ return true ;
1198
+ }
1199
+
1200
+ bool X509View::ifEc (KeyCallback<Ec> callback) const {
1201
+ if (cert_ == nullptr ) return true ;
1202
+ OSSL3_CONST EVP_PKEY* pkey = X509_get0_pubkey (cert_);
1203
+ OSSL3_CONST EC_KEY* ec = nullptr ;
1204
+ auto id = EVP_PKEY_id (pkey);
1205
+ if (id == EVP_PKEY_EC) {
1206
+ Ec ec (EVP_PKEY_get0_EC_KEY (pkey));
1207
+ if (!ec) [[unlikely]]
1208
+ return true ;
1209
+ return callback (ec);
1210
+ }
1211
+ return true ;
1212
+ }
1213
+
1163
1214
X509Pointer X509Pointer::IssuerFrom (const SSLPointer& ssl,
1164
1215
const X509View& view) {
1165
1216
return IssuerFrom (SSL_get_SSL_CTX (ssl.get ()), view);
@@ -2287,15 +2338,26 @@ Result<BIOPointer, bool> EVPKeyPointer::writePublicKey(
2287
2338
}
2288
2339
2289
2340
bool EVPKeyPointer::isRsaVariant () const {
2341
+ if (!pkey_) return false ;
2290
2342
int type = id ();
2291
- return type == EVP_PKEY_RSA ||
2292
- type == EVP_PKEY_RSA2 ||
2343
+ return type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2 ||
2293
2344
type == EVP_PKEY_RSA_PSS;
2294
2345
}
2295
2346
2347
+ bool EVPKeyPointer::isOneShotVariant () const {
2348
+ if (!pkey_) return false ;
2349
+ int type = id ();
2350
+ return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
2351
+ }
2352
+
2353
+ bool EVPKeyPointer::isSigVariant () const {
2354
+ if (!pkey_) return false ;
2355
+ int type = id ();
2356
+ return type == EVP_PKEY_EC || type == EVP_PKEY_DSA;
2357
+ }
2358
+
2296
2359
int EVPKeyPointer::getDefaultSignPadding () const {
2297
- return id () == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING
2298
- : RSA_PKCS1_PADDING;
2360
+ return id () == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
2299
2361
}
2300
2362
2301
2363
std::optional<uint32_t > EVPKeyPointer::getBytesOfRS () const {
@@ -2331,6 +2393,28 @@ EVPKeyPointer::operator Rsa() const {
2331
2393
return Rsa (rsa);
2332
2394
}
2333
2395
2396
+ bool EVPKeyPointer::validateDsaParameters () const {
2397
+ if (!pkey_) return false ;
2398
+ /* Validate DSA2 parameters from FIPS 186-4 */
2399
+ #if OPENSSL_VERSION_MAJOR >= 3
2400
+ if (EVP_default_properties_is_fips_enabled (nullptr ) && EVP_PKEY_DSA == id ()) {
2401
+ #else
2402
+ if (FIPS_mode () && EVP_PKEY_DSA == id ()) {
2403
+ #endif
2404
+ const DSA* dsa = EVP_PKEY_get0_DSA (pkey_.get ());
2405
+ const BIGNUM* p;
2406
+ const BIGNUM* q;
2407
+ DSA_get0_pqg (dsa, &p, &q, nullptr );
2408
+ int L = BignumPointer::GetBitCount (p);
2409
+ int N = BignumPointer::GetBitCount (q);
2410
+
2411
+ return (L == 1024 && N == 160 ) || (L == 2048 && N == 224 ) ||
2412
+ (L == 2048 && N == 256 ) || (L == 3072 && N == 256 );
2413
+ }
2414
+
2415
+ return true ;
2416
+ }
2417
+
2334
2418
// ============================================================================
2335
2419
2336
2420
SSLPointer::SSLPointer (SSL* ssl) : ssl_ (ssl) {}
@@ -3203,6 +3287,42 @@ bool EVPKeyCtxPointer::privateCheck() const {
3203
3287
return EVP_PKEY_check (ctx_.get ()) == 1 ;
3204
3288
}
3205
3289
3290
+ bool EVPKeyCtxPointer::verify (const Buffer<const unsigned char >& sig,
3291
+ const Buffer<const unsigned char >& data) {
3292
+ if (!ctx_) return false ;
3293
+ return EVP_PKEY_verify (ctx_.get (), sig.data , sig.len , data.data , data.len ) ==
3294
+ 1 ;
3295
+ }
3296
+
3297
+ DataPointer EVPKeyCtxPointer::sign (const Buffer<const unsigned char >& data) {
3298
+ if (!ctx_) return {};
3299
+ size_t len = 0 ;
3300
+ if (EVP_PKEY_sign (ctx_.get (), nullptr , &len, data.data , data.len ) != 1 ) {
3301
+ return {};
3302
+ }
3303
+ auto buf = DataPointer::Alloc (len);
3304
+ if (!buf) return {};
3305
+ if (EVP_PKEY_sign (ctx_.get (),
3306
+ static_cast <unsigned char *>(buf.get ()),
3307
+ &len,
3308
+ data.data ,
3309
+ data.len ) != 1 ) {
3310
+ return {};
3311
+ }
3312
+ return buf.resize (len);
3313
+ }
3314
+
3315
+ bool EVPKeyCtxPointer::signInto (const Buffer<const unsigned char >& data,
3316
+ Buffer<unsigned char >* sig) {
3317
+ if (!ctx_) return false ;
3318
+ size_t len = sig->len ;
3319
+ if (EVP_PKEY_sign (ctx_.get (), sig->data , &len, data.data , data.len ) != 1 ) {
3320
+ return false ;
3321
+ }
3322
+ sig->len = len;
3323
+ return true ;
3324
+ }
3325
+
3206
3326
// ============================================================================
3207
3327
3208
3328
namespace {
@@ -3431,6 +3551,20 @@ DataPointer Cipher::recover(const EVPKeyPointer& key,
3431
3551
3432
3552
// ============================================================================
3433
3553
3554
+ Ec::Ec () : ec_ (nullptr ) {}
3555
+
3556
+ Ec::Ec (const EC_KEY* key) : ec_ (key) {}
3557
+
3558
+ const EC_GROUP* Ec::getGroup () const {
3559
+ return ECKeyPointer::GetGroup (ec_);
3560
+ }
3561
+
3562
+ int Ec::getCurve () const {
3563
+ return EC_GROUP_get_curve_name (getGroup ());
3564
+ }
3565
+
3566
+ // ============================================================================
3567
+
3434
3568
EVPMDCtxPointer::EVPMDCtxPointer () : ctx_ (nullptr ) {}
3435
3569
3436
3570
EVPMDCtxPointer::EVPMDCtxPointer (EVP_MD_CTX* ctx) : ctx_ (ctx) {}
@@ -3443,9 +3577,13 @@ EVPMDCtxPointer& EVPMDCtxPointer::operator=(EVPMDCtxPointer&& other) noexcept {
3443
3577
return *this ;
3444
3578
}
3445
3579
3446
- EVPMDCtxPointer::~EVPMDCtxPointer () { reset (); }
3580
+ EVPMDCtxPointer::~EVPMDCtxPointer () {
3581
+ reset ();
3582
+ }
3447
3583
3448
- void EVPMDCtxPointer::reset (EVP_MD_CTX* ctx) { ctx_.reset (ctx); }
3584
+ void EVPMDCtxPointer::reset (EVP_MD_CTX* ctx) {
3585
+ ctx_.reset (ctx);
3586
+ }
3449
3587
3450
3588
EVP_MD_CTX* EVPMDCtxPointer::release () {
3451
3589
return ctx_.release ();
@@ -3466,18 +3604,31 @@ DataPointer EVPMDCtxPointer::digestFinal(size_t length) {
3466
3604
3467
3605
auto buf = DataPointer::Alloc (length);
3468
3606
if (!buf) return {};
3469
- auto ptr = static_cast <unsigned char *>(buf.get ());
3470
3607
3471
- int ret =
3472
- (length == getExpectedSize ())
3473
- ? EVP_DigestFinal_ex (ctx_.get (), ptr, nullptr )
3474
- : EVP_DigestFinalXOF (ctx_.get (), ptr, length);
3608
+ Buffer<void > buffer = buf;
3475
3609
3476
- if (ret != 1 ) [[unlikely]] return {};
3610
+ if (!digestFinalInto (&buffer)) [[unlikely]] {
3611
+ return {};
3612
+ }
3477
3613
3478
3614
return buf;
3479
3615
}
3480
3616
3617
+ bool EVPMDCtxPointer::digestFinalInto (Buffer<void >* buf) {
3618
+ if (!ctx_) false ;
3619
+
3620
+ auto ptr = static_cast <unsigned char *>(buf->data );
3621
+
3622
+ int ret = (buf->len == getExpectedSize ())
3623
+ ? EVP_DigestFinal_ex (ctx_.get (), ptr, nullptr )
3624
+ : EVP_DigestFinalXOF (ctx_.get (), ptr, buf->len );
3625
+
3626
+ if (ret != 1 ) [[unlikely]]
3627
+ return false ;
3628
+
3629
+ return true ;
3630
+ }
3631
+
3481
3632
size_t EVPMDCtxPointer::getExpectedSize () {
3482
3633
if (!ctx_) return 0 ;
3483
3634
return EVP_MD_CTX_size (ctx_.get ());
@@ -3498,13 +3649,90 @@ bool EVPMDCtxPointer::hasXofFlag() const {
3498
3649
}
3499
3650
3500
3651
bool EVPMDCtxPointer::copyTo (const EVPMDCtxPointer& other) const {
3501
- if (!ctx_ ||!other) return {};
3652
+ if (!ctx_ || !other) return {};
3502
3653
if (EVP_MD_CTX_copy (other.get (), ctx_.get ()) != 1 ) return false ;
3503
3654
return true ;
3504
3655
}
3505
3656
3657
+ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit (const EVPKeyPointer& key,
3658
+ const EVP_MD* digest) {
3659
+ EVP_PKEY_CTX* ctx = nullptr ;
3660
+ if (!EVP_DigestSignInit (ctx_.get (), &ctx, digest, nullptr , key.get ())) {
3661
+ return std::nullopt;
3662
+ }
3663
+ return ctx;
3664
+ }
3665
+
3666
+ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::verifyInit (
3667
+ const EVPKeyPointer& key, const EVP_MD* digest) {
3668
+ EVP_PKEY_CTX* ctx = nullptr ;
3669
+ if (!EVP_DigestVerifyInit (ctx_.get (), &ctx, digest, nullptr , key.get ())) {
3670
+ return std::nullopt;
3671
+ }
3672
+ return ctx;
3673
+ }
3674
+
3675
+ DataPointer EVPMDCtxPointer::signOneShot (
3676
+ const Buffer<const unsigned char >& buf) const {
3677
+ if (!ctx_) return {};
3678
+ size_t len;
3679
+ if (!EVP_DigestSign (ctx_.get (), nullptr , &len, buf.data , buf.len )) {
3680
+ return {};
3681
+ }
3682
+ auto data = DataPointer::Alloc (len);
3683
+ if (!data) [[unlikely]]
3684
+ return {};
3685
+
3686
+ if (!EVP_DigestSign (ctx_.get (),
3687
+ static_cast <unsigned char *>(data.get ()),
3688
+ &len,
3689
+ buf.data ,
3690
+ buf.len )) {
3691
+ return {};
3692
+ }
3693
+ return data;
3694
+ }
3695
+
3696
+ DataPointer EVPMDCtxPointer::sign (
3697
+ const Buffer<const unsigned char >& buf) const {
3698
+ if (!ctx_) [[unlikely]]
3699
+ return {};
3700
+ size_t len;
3701
+ if (!EVP_DigestSignUpdate (ctx_.get (), buf.data , buf.len ) ||
3702
+ !EVP_DigestSignFinal (ctx_.get (), nullptr , &len)) {
3703
+ return {};
3704
+ }
3705
+ auto data = DataPointer::Alloc (len);
3706
+ if (!data) [[unlikely]]
3707
+ return {};
3708
+ if (!EVP_DigestSignFinal (
3709
+ ctx_.get (), static_cast <unsigned char *>(data.get ()), &len)) {
3710
+ return {};
3711
+ }
3712
+ return data.resize (len);
3713
+ }
3714
+
3715
+ bool EVPMDCtxPointer::verify (const Buffer<const unsigned char >& buf,
3716
+ const Buffer<const unsigned char >& sig) const {
3717
+ if (!ctx_) return false ;
3718
+ int ret = EVP_DigestVerify (ctx_.get (), sig.data , sig.len , buf.data , buf.len );
3719
+ return ret == 1 ;
3720
+ }
3721
+
3506
3722
EVPMDCtxPointer EVPMDCtxPointer::New () {
3507
3723
return EVPMDCtxPointer (EVP_MD_CTX_new ());
3508
3724
}
3509
3725
3726
+ // ============================================================================
3727
+
3728
+ bool extractP1363 (const Buffer<const unsigned char >& buf,
3729
+ unsigned char * dest,
3730
+ size_t n) {
3731
+ auto asn1_sig = ECDSASigPointer::Parse (buf);
3732
+ if (!asn1_sig) return false ;
3733
+
3734
+ return BignumPointer::EncodePaddedInto (asn1_sig.r (), dest, n) > 0 &&
3735
+ BignumPointer::EncodePaddedInto (asn1_sig.s (), dest + n, n) > 0 ;
3736
+ }
3737
+
3510
3738
} // namespace ncrypto
0 commit comments