@@ -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);
@@ -2273,15 +2324,26 @@ Result<BIOPointer, bool> EVPKeyPointer::writePublicKey(
2273
2324
}
2274
2325
2275
2326
bool EVPKeyPointer::isRsaVariant () const {
2327
+ if (!pkey_) return false ;
2276
2328
int type = id ();
2277
- return type == EVP_PKEY_RSA ||
2278
- type == EVP_PKEY_RSA2 ||
2329
+ return type == EVP_PKEY_RSA || type == EVP_PKEY_RSA2 ||
2279
2330
type == EVP_PKEY_RSA_PSS;
2280
2331
}
2281
2332
2333
+ bool EVPKeyPointer::isOneShotVariant () const {
2334
+ if (!pkey_) return false ;
2335
+ int type = id ();
2336
+ return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
2337
+ }
2338
+
2339
+ bool EVPKeyPointer::isSigVariant () const {
2340
+ if (!pkey_) return false ;
2341
+ int type = id ();
2342
+ return type == EVP_PKEY_EC || type == EVP_PKEY_DSA;
2343
+ }
2344
+
2282
2345
int EVPKeyPointer::getDefaultSignPadding () const {
2283
- return id () == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING
2284
- : RSA_PKCS1_PADDING;
2346
+ return id () == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
2285
2347
}
2286
2348
2287
2349
std::optional<uint32_t > EVPKeyPointer::getBytesOfRS () const {
@@ -2317,6 +2379,28 @@ EVPKeyPointer::operator Rsa() const {
2317
2379
return Rsa (rsa);
2318
2380
}
2319
2381
2382
+ bool EVPKeyPointer::validateDsaParameters () const {
2383
+ if (!pkey_) return false ;
2384
+ /* Validate DSA2 parameters from FIPS 186-4 */
2385
+ #if OPENSSL_VERSION_MAJOR >= 3
2386
+ if (EVP_default_properties_is_fips_enabled (nullptr ) && EVP_PKEY_DSA == id ()) {
2387
+ #else
2388
+ if (FIPS_mode () && EVP_PKEY_DSA == id ()) {
2389
+ #endif
2390
+ const DSA* dsa = EVP_PKEY_get0_DSA (pkey_.get ());
2391
+ const BIGNUM* p;
2392
+ const BIGNUM* q;
2393
+ DSA_get0_pqg (dsa, &p, &q, nullptr );
2394
+ int L = BignumPointer::GetBitCount (p);
2395
+ int N = BignumPointer::GetBitCount (q);
2396
+
2397
+ return (L == 1024 && N == 160 ) || (L == 2048 && N == 224 ) ||
2398
+ (L == 2048 && N == 256 ) || (L == 3072 && N == 256 );
2399
+ }
2400
+
2401
+ return true ;
2402
+ }
2403
+
2320
2404
// ============================================================================
2321
2405
2322
2406
SSLPointer::SSLPointer (SSL* ssl) : ssl_ (ssl) {}
@@ -3189,6 +3273,42 @@ bool EVPKeyCtxPointer::privateCheck() const {
3189
3273
return EVP_PKEY_check (ctx_.get ()) == 1 ;
3190
3274
}
3191
3275
3276
+ bool EVPKeyCtxPointer::verify (const Buffer<const unsigned char >& sig,
3277
+ const Buffer<const unsigned char >& data) {
3278
+ if (!ctx_) return false ;
3279
+ return EVP_PKEY_verify (ctx_.get (), sig.data , sig.len , data.data , data.len ) ==
3280
+ 1 ;
3281
+ }
3282
+
3283
+ DataPointer EVPKeyCtxPointer::sign (const Buffer<const unsigned char >& data) {
3284
+ if (!ctx_) return {};
3285
+ size_t len = 0 ;
3286
+ if (EVP_PKEY_sign (ctx_.get (), nullptr , &len, data.data , data.len ) != 1 ) {
3287
+ return {};
3288
+ }
3289
+ auto buf = DataPointer::Alloc (len);
3290
+ if (!buf) return {};
3291
+ if (EVP_PKEY_sign (ctx_.get (),
3292
+ static_cast <unsigned char *>(buf.get ()),
3293
+ &len,
3294
+ data.data ,
3295
+ data.len ) != 1 ) {
3296
+ return {};
3297
+ }
3298
+ return buf.resize (len);
3299
+ }
3300
+
3301
+ bool EVPKeyCtxPointer::signInto (const Buffer<const unsigned char >& data,
3302
+ Buffer<unsigned char >* sig) {
3303
+ if (!ctx_) return false ;
3304
+ size_t len = sig->len ;
3305
+ if (EVP_PKEY_sign (ctx_.get (), sig->data , &len, data.data , data.len ) != 1 ) {
3306
+ return false ;
3307
+ }
3308
+ sig->len = len;
3309
+ return true ;
3310
+ }
3311
+
3192
3312
// ============================================================================
3193
3313
3194
3314
namespace {
@@ -3417,6 +3537,20 @@ DataPointer Cipher::recover(const EVPKeyPointer& key,
3417
3537
3418
3538
// ============================================================================
3419
3539
3540
+ Ec::Ec () : ec_ (nullptr ) {}
3541
+
3542
+ Ec::Ec (const EC_KEY* key) : ec_ (key) {}
3543
+
3544
+ const EC_GROUP* Ec::getGroup () const {
3545
+ return ECKeyPointer::GetGroup (ec_);
3546
+ }
3547
+
3548
+ int Ec::getCurve () const {
3549
+ return EC_GROUP_get_curve_name (getGroup ());
3550
+ }
3551
+
3552
+ // ============================================================================
3553
+
3420
3554
EVPMDCtxPointer::EVPMDCtxPointer () : ctx_ (nullptr ) {}
3421
3555
3422
3556
EVPMDCtxPointer::EVPMDCtxPointer (EVP_MD_CTX* ctx) : ctx_ (ctx) {}
@@ -3429,9 +3563,13 @@ EVPMDCtxPointer& EVPMDCtxPointer::operator=(EVPMDCtxPointer&& other) noexcept {
3429
3563
return *this ;
3430
3564
}
3431
3565
3432
- EVPMDCtxPointer::~EVPMDCtxPointer () { reset (); }
3566
+ EVPMDCtxPointer::~EVPMDCtxPointer () {
3567
+ reset ();
3568
+ }
3433
3569
3434
- void EVPMDCtxPointer::reset (EVP_MD_CTX* ctx) { ctx_.reset (ctx); }
3570
+ void EVPMDCtxPointer::reset (EVP_MD_CTX* ctx) {
3571
+ ctx_.reset (ctx);
3572
+ }
3435
3573
3436
3574
EVP_MD_CTX* EVPMDCtxPointer::release () {
3437
3575
return ctx_.release ();
@@ -3452,18 +3590,31 @@ DataPointer EVPMDCtxPointer::digestFinal(size_t length) {
3452
3590
3453
3591
auto buf = DataPointer::Alloc (length);
3454
3592
if (!buf) return {};
3455
- auto ptr = static_cast <unsigned char *>(buf.get ());
3456
3593
3457
- int ret =
3458
- (length == getExpectedSize ())
3459
- ? EVP_DigestFinal_ex (ctx_.get (), ptr, nullptr )
3460
- : EVP_DigestFinalXOF (ctx_.get (), ptr, length);
3594
+ Buffer<void > buffer = buf;
3461
3595
3462
- if (ret != 1 ) [[unlikely]] return {};
3596
+ if (!digestFinalInto (&buffer)) [[unlikely]] {
3597
+ return {};
3598
+ }
3463
3599
3464
3600
return buf;
3465
3601
}
3466
3602
3603
+ bool EVPMDCtxPointer::digestFinalInto (Buffer<void >* buf) {
3604
+ if (!ctx_) false ;
3605
+
3606
+ auto ptr = static_cast <unsigned char *>(buf->data );
3607
+
3608
+ int ret = (buf->len == getExpectedSize ())
3609
+ ? EVP_DigestFinal_ex (ctx_.get (), ptr, nullptr )
3610
+ : EVP_DigestFinalXOF (ctx_.get (), ptr, buf->len );
3611
+
3612
+ if (ret != 1 ) [[unlikely]]
3613
+ return false ;
3614
+
3615
+ return true ;
3616
+ }
3617
+
3467
3618
size_t EVPMDCtxPointer::getExpectedSize () {
3468
3619
if (!ctx_) return 0 ;
3469
3620
return EVP_MD_CTX_size (ctx_.get ());
@@ -3484,13 +3635,90 @@ bool EVPMDCtxPointer::hasXofFlag() const {
3484
3635
}
3485
3636
3486
3637
bool EVPMDCtxPointer::copyTo (const EVPMDCtxPointer& other) const {
3487
- if (!ctx_ ||!other) return {};
3638
+ if (!ctx_ || !other) return {};
3488
3639
if (EVP_MD_CTX_copy (other.get (), ctx_.get ()) != 1 ) return false ;
3489
3640
return true ;
3490
3641
}
3491
3642
3643
+ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit (const EVPKeyPointer& key,
3644
+ const EVP_MD* digest) {
3645
+ EVP_PKEY_CTX* ctx = nullptr ;
3646
+ if (!EVP_DigestSignInit (ctx_.get (), &ctx, digest, nullptr , key.get ())) {
3647
+ return std::nullopt;
3648
+ }
3649
+ return ctx;
3650
+ }
3651
+
3652
+ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::verifyInit (
3653
+ const EVPKeyPointer& key, const EVP_MD* digest) {
3654
+ EVP_PKEY_CTX* ctx = nullptr ;
3655
+ if (!EVP_DigestVerifyInit (ctx_.get (), &ctx, digest, nullptr , key.get ())) {
3656
+ return std::nullopt;
3657
+ }
3658
+ return ctx;
3659
+ }
3660
+
3661
+ DataPointer EVPMDCtxPointer::signOneShot (
3662
+ const Buffer<const unsigned char >& buf) const {
3663
+ if (!ctx_) return {};
3664
+ size_t len;
3665
+ if (!EVP_DigestSign (ctx_.get (), nullptr , &len, buf.data , buf.len )) {
3666
+ return {};
3667
+ }
3668
+ auto data = DataPointer::Alloc (len);
3669
+ if (!data) [[unlikely]]
3670
+ return {};
3671
+
3672
+ if (!EVP_DigestSign (ctx_.get (),
3673
+ static_cast <unsigned char *>(data.get ()),
3674
+ &len,
3675
+ buf.data ,
3676
+ buf.len )) {
3677
+ return {};
3678
+ }
3679
+ return data;
3680
+ }
3681
+
3682
+ DataPointer EVPMDCtxPointer::sign (
3683
+ const Buffer<const unsigned char >& buf) const {
3684
+ if (!ctx_) [[unlikely]]
3685
+ return {};
3686
+ size_t len;
3687
+ if (!EVP_DigestSignUpdate (ctx_.get (), buf.data , buf.len ) ||
3688
+ !EVP_DigestSignFinal (ctx_.get (), nullptr , &len)) {
3689
+ return {};
3690
+ }
3691
+ auto data = DataPointer::Alloc (len);
3692
+ if (!data) [[unlikely]]
3693
+ return {};
3694
+ if (!EVP_DigestSignFinal (
3695
+ ctx_.get (), static_cast <unsigned char *>(data.get ()), &len)) {
3696
+ return {};
3697
+ }
3698
+ return data.resize (len);
3699
+ }
3700
+
3701
+ bool EVPMDCtxPointer::verify (const Buffer<const unsigned char >& buf,
3702
+ const Buffer<const unsigned char >& sig) const {
3703
+ if (!ctx_) return false ;
3704
+ int ret = EVP_DigestVerify (ctx_.get (), sig.data , sig.len , buf.data , buf.len );
3705
+ return ret == 1 ;
3706
+ }
3707
+
3492
3708
EVPMDCtxPointer EVPMDCtxPointer::New () {
3493
3709
return EVPMDCtxPointer (EVP_MD_CTX_new ());
3494
3710
}
3495
3711
3712
+ // ============================================================================
3713
+
3714
+ bool extractP1363 (const Buffer<const unsigned char >& buf,
3715
+ unsigned char * dest,
3716
+ size_t n) {
3717
+ auto asn1_sig = ECDSASigPointer::Parse (buf);
3718
+ if (!asn1_sig) return false ;
3719
+
3720
+ return BignumPointer::EncodePaddedInto (asn1_sig.r (), dest, n) > 0 &&
3721
+ BignumPointer::EncodePaddedInto (asn1_sig.s (), dest + n, n) > 0 ;
3722
+ }
3723
+
3496
3724
} // namespace ncrypto
0 commit comments