Skip to content

Commit

Permalink
Potentially fix CMS Data Envelope creation for ECC certificates (#1003)
Browse files Browse the repository at this point in the history
* Attempt support for ECC certificates

This generates an ephemeral EC-DH key pair for KeyAgreement within the
context of the CMS data envelope, using the same underlying curve as the
recipient's certificate.

Signed-off-by: Alexander Scheel <[email protected]>

* Bump BouncyCastle to 2.3.0 for SPKI OID information

Signed-off-by: Alexander Scheel <[email protected]>

---------

Signed-off-by: Alexander Scheel <[email protected]>
  • Loading branch information
cipherboy authored Feb 8, 2024
1 parent 9dbb4e6 commit 3f526df
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
47 changes: 44 additions & 3 deletions MimeKit/Cryptography/BouncyCastleSecureMimeContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1225,11 +1225,11 @@ public override Stream Verify (Stream signedData, out DigitalSignatureCollection
}
}

class CmsRecipientInfoGenerator : RecipientInfoGenerator
class OaepAwareRecipientInfoGenerator : RecipientInfoGenerator
{
readonly CmsRecipient recipient;

public CmsRecipientInfoGenerator (CmsRecipient recipient)
public OaepAwareRecipientInfoGenerator (CmsRecipient recipient)
{
this.recipient = recipient;
}
Expand Down Expand Up @@ -1268,6 +1268,9 @@ public RecipientInfo Generate (KeyParameter contentEncryptionKey, SecureRandom r
var publicKeyInfo = certificate.SubjectPublicKeyInfo;
AlgorithmIdentifier keyEncryptionAlgorithm;

// If the recipient explicitly opts in to OAEP encryption (even if
// the underlying certificate is not tagged with an OAEP OID),
// choose OAEP instead.
if (publicKey is RsaKeyParameters && recipient.RsaEncryptionPadding?.Scheme == RsaEncryptionPaddingScheme.Oaep) {
keyEncryptionAlgorithm = recipient.RsaEncryptionPadding.GetAlgorithmIdentifier ();
} else {
Expand Down Expand Up @@ -1300,7 +1303,45 @@ Stream Envelope (CmsRecipientCollection recipients, Stream content, Cancellation

foreach (var recipient in recipients) {
if (unique.Add (recipient.Certificate)) {
cms.AddRecipientInfoGenerator (new CmsRecipientInfoGenerator (recipient));
var cert = recipient.Certificate;
var pub = recipient.Certificate.GetPublicKey();
if (pub is RsaKeyParameters) {
// Bouncy Castle dispatches OAEP based off the certificate type.
// However, callers of MimeKit expect to use OAEP in S/MIME with
// certificates with PKCS#1v1.5 OIDs as these tend to be more broadly
// compatible across the ecosystem. Thus, buidl our own
// RecipientInfoGenerator and register that for this key.
cms.AddRecipientInfoGenerator (new OaepAwareRecipientInfoGenerator (recipient));
} else if (pub is ECKeyParameters) {
var ecPub = (ECKeyParameters) pub;
var kg = GeneratorUtilities.GetKeyPairGenerator ("ECDH");
kg.Init(new ECKeyGenerationParameters (ecPub.Parameters, RandomNumberGenerator));
var kp = kg.GenerateKeyPair ();

// TODO: better handle algorithm selection.
if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier) {
var subjectKeyIdentifier = recipient.Certificate.GetExtensionValue (X509Extensions.SubjectKeyIdentifier);
cms.AddKeyAgreementRecipient (
CmsEnvelopedDataGenerator.ECDHSha1Kdf,
kp.Public,
kp.Private,
subjectKeyIdentifier.GetOctets (),
pub,
CmsEnvelopedGenerator.Aes128Wrap
);
} else {
cms.AddKeyAgreementRecipient (
CmsEnvelopedDataGenerator.ECDHSha1Kdf,
kp.Public,
kp.Private,
cert,
CmsEnvelopedGenerator.Aes128Wrap
);
}
} else {
var oid = cert.SubjectPublicKeyInfo.Algorithm.Algorithm.ToString();
throw new ArgumentException("Unknown type of recipient certificate: " + pub.GetType().Name + " (SubjectPublicKeyInfo OID = " + oid + ")");
}
count++;
}
}
Expand Down
2 changes: 1 addition & 1 deletion MimeKit/MimeKit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@
<Compile Include="Utils\OptimizedOrdinalComparer.cs" Condition=" $(TargetFramework.StartsWith('net4')) Or '$(TargetFramework)' == 'netstandard2.0' " />
</ItemGroup>

</Project>
</Project>

0 comments on commit 3f526df

Please sign in to comment.