diff --git a/crypto/src/crmf/AuthenticatorControl.cs b/crypto/src/crmf/AuthenticatorControl.cs
new file mode 100644
index 000000000..7803c4418
--- /dev/null
+++ b/crypto/src/crmf/AuthenticatorControl.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class AuthenticatorControl:IControl
+ {
+
+ private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_authenticator;
+
+ private readonly DerUtf8String token;
+
+ public AuthenticatorControl(DerUtf8String token)
+ {
+ this.token = token;
+ }
+
+ public AuthenticatorControl(String token)
+ {
+ this.token = new DerUtf8String(token);
+ }
+
+ public DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+
+ public Asn1Encodable Value {
+ get { return token; }
+ }
+ }
+}
diff --git a/crypto/src/crmf/CertificateRequestMessage.cs b/crypto/src/crmf/CertificateRequestMessage.cs
new file mode 100644
index 000000000..818facade
--- /dev/null
+++ b/crypto/src/crmf/CertificateRequestMessage.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class CertificateRequestMessage
+ {
+ public static readonly int popRaVerified = Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.TYPE_RA_VERIFIED;
+ public static readonly int popSigningKey = Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.TYPE_SIGNING_KEY;
+ public static readonly int popKeyEncipherment = Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ public static readonly int popKeyAgreement = Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.TYPE_KEY_AGREEMENT;
+
+ private readonly CertReqMsg certReqMsg;
+ private readonly Controls controls;
+
+ private static CertReqMsg ParseBytes(byte[] encoding)
+
+ {
+ return CertReqMsg.GetInstance(encoding);
+ }
+
+ public CertificateRequestMessage(CertReqMsg certReqMsg)
+ {
+ this.certReqMsg = certReqMsg;
+ this.controls = certReqMsg.CertReq.Controls;
+ }
+
+ public CertReqMsg ToAsn1Structure()
+ {
+ return certReqMsg;
+ }
+
+ public CertTemplate GetCertTemplate()
+ {
+ return this.certReqMsg.CertReq.CertTemplate;
+ }
+
+ public bool HasControls
+ {
+ get { return controls != null; }
+ }
+
+
+ public bool HasControl(DerObjectIdentifier objectIdentifier)
+ {
+ return findControl(objectIdentifier) != null;
+ }
+
+ public IControl GetControl(DerObjectIdentifier type)
+ {
+ AttributeTypeAndValue found = findControl(type);
+ if (found != null)
+ {
+ if (found.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_pkiArchiveOptions))
+ {
+ return new PkiArchiveControl(PkiArchiveOptions.GetInstance(found.Value));
+ }
+
+ if (found.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_regToken))
+ {
+ return new RegTokenControl(DerUtf8String.GetInstance(found.Value));
+ }
+
+ if (found.Type.Equals(CrmfObjectIdentifiers.id_regCtrl_authenticator))
+ {
+ return new AuthenticatorControl(DerUtf8String.GetInstance(found.Value));
+ }
+ }
+ return null;
+ }
+
+
+
+
+ public AttributeTypeAndValue findControl(DerObjectIdentifier type)
+ {
+ if (controls == null)
+ {
+ return null;
+ }
+
+ AttributeTypeAndValue[] tAndV = controls.ToAttributeTypeAndValueArray();
+ AttributeTypeAndValue found = null;
+
+ for (int i = 0; i < tAndV.Length; i++)
+ {
+ if (tAndV[i].Type.Equals(type))
+ {
+ found = tAndV[i];
+ break;
+ }
+ }
+
+ return found;
+ }
+
+ public bool HasProofOfPossession
+ {
+ get { return certReqMsg.Popo != null; }
+ }
+
+ public int ProofOfPossession
+ {
+ get { return certReqMsg.Popo.Type; }
+ }
+
+ public bool HasSigningKeyProofOfPossessionWithPkMac
+ {
+ get
+ {
+ ProofOfPossession pop = certReqMsg.Popo;
+
+ if (pop.Type == popSigningKey)
+ {
+ PopoSigningKey popoSign = PopoSigningKey.GetInstance(pop.Object);
+
+ return popoSign.PoposkInput.PublicKeyMac != null;
+ }
+
+ return false;
+
+ }
+ }
+
+ public bool IsValidSigningKeyPop(IVerifierFactoryProvider verifierProvider)
+ {
+ ProofOfPossession pop = certReqMsg.Popo;
+ if (pop.Type == popSigningKey)
+ {
+ PopoSigningKey popoSign = PopoSigningKey.GetInstance(pop.Object);
+ if (popoSign.PoposkInput != null && popoSign.PoposkInput.PublicKeyMac != null)
+ {
+ throw new InvalidOperationException("verification requires password check");
+ }
+ return verifySignature(verifierProvider, popoSign);
+ }
+
+ throw new InvalidOperationException("not Signing Key type of proof of possession");
+ }
+
+
+
+ private bool verifySignature(IVerifierFactoryProvider verifierFactoryProvider, PopoSigningKey signKey)
+ {
+ IVerifierFactory verifer;
+ IStreamCalculator calculator;
+ try
+ {
+ verifer = verifierFactoryProvider.CreateVerifierFactory(signKey.AlgorithmIdentifier);
+ calculator = verifer.CreateCalculator();
+ }
+ catch (Exception ex)
+ {
+ throw new CrmfException("unable to create verifier: "+ex.Message, ex);
+ }
+
+ if (signKey.PoposkInput != null)
+ {
+ byte[] b = signKey.GetDerEncoded();
+ calculator.Stream.Write(b,0,b.Length);
+ }
+ else
+ {
+ byte[] b = certReqMsg.GetDerEncoded();
+ calculator.Stream.Write(b,0,b.Length);
+ }
+
+ DefaultVerifierResult result = (DefaultVerifierResult) calculator.GetResult();
+
+ return result.IsVerified(signKey.Signature.GetBytes());
+ }
+
+ public byte[] GetEncoded()
+ {
+ return certReqMsg.GetEncoded();
+ }
+ }
+}
diff --git a/crypto/src/crmf/CertificateRequestMessageBuilder.cs b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
new file mode 100644
index 000000000..53ebdf3f5
--- /dev/null
+++ b/crypto/src/crmf/CertificateRequestMessageBuilder.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class CertificateRequestMessageBuilder
+ {
+ private readonly BigInteger _certReqId;
+ private X509ExtensionsGenerator _extGenerator;
+ private CertTemplateBuilder _templateBuilder;
+ private ArrayList _controls= new ArrayList();
+ private ISignatureFactory _popSigner;
+ private PkMacFactory _pkMacBuilder;
+ private char[] _password;
+ private GeneralName _sender;
+ private int _popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ private PopoPrivKey _popoPrivKey;
+ private Asn1Null _popRaVerified;
+ private PKMacValue _agreeMac;
+
+ public CertificateRequestMessageBuilder(BigInteger certReqId)
+ {
+ this._certReqId = certReqId;
+ this._extGenerator = new X509ExtensionsGenerator();
+ this._templateBuilder = new CertTemplateBuilder();
+ }
+
+ public CertificateRequestMessageBuilder SetPublicKey(SubjectPublicKeyInfo publicKeyInfo)
+ {
+ if (publicKeyInfo != null)
+ {
+ _templateBuilder.SetPublicKey(publicKeyInfo);
+ }
+
+ return this;
+ }
+
+
+ public CertificateRequestMessageBuilder SetIssuer(X509Name issuer)
+ {
+ if (issuer != null)
+ {
+ _templateBuilder.SetIssuer(issuer);
+ }
+
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetSubject(X509Name subject)
+ {
+ if (subject != null)
+ {
+ _templateBuilder.SetSubject(subject);
+ }
+
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetSerialNumber(BigInteger serialNumber)
+ {
+ if (serialNumber != null)
+ {
+ _templateBuilder.SetSerialNumber(new DerInteger(serialNumber));
+ }
+
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetValidity(Time notBefore, Time notAfter)
+ {
+ _templateBuilder.SetValidity(new OptionalValidity(notBefore, notAfter));
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder AddExtension(DerObjectIdentifier oid, bool critical,
+ Asn1Encodable value)
+ {
+ _extGenerator.AddExtension(oid,critical, value);
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder AddExtension(DerObjectIdentifier oid, bool critical,
+ byte[] value)
+ {
+ _extGenerator.AddExtension(oid, critical, value);
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetProofOfPossessionSignKeySigner(ISignatureFactory popoSignatureFactory)
+ {
+ if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
+ {
+ throw new InvalidOperationException("only one proof of possession is allowed.");
+ }
+
+ this._popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetProofOfPossessionSubsequentMessage(SubsequentMessage msg)
+ {
+ if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
+ {
+ throw new InvalidOperationException("only one proof of possession is allowed.");
+ }
+
+ this._popoType = ProofOfPossession.TYPE_KEY_ENCIPHERMENT;
+ this._popoPrivKey = new PopoPrivKey(msg);
+
+
+ return this;
+ }
+
+
+ public CertificateRequestMessageBuilder SetProofOfPossessionSubsequentMessage(int type, SubsequentMessage msg)
+ {
+ if (_popoPrivKey != null || _popRaVerified != null || _agreeMac != null)
+ {
+ throw new InvalidOperationException("only one proof of possession is allowed.");
+ }
+
+ if (type != ProofOfPossession.TYPE_KEY_ENCIPHERMENT && type != ProofOfPossession.TYPE_KEY_AGREEMENT)
+ {
+ throw new ArgumentException("type must be ProofOfPossession.TYPE_KEY_ENCIPHERMENT || ProofOfPossession.TYPE_KEY_AGREEMENT");
+ }
+
+ this._popoType = type;
+ this._popoPrivKey = new PopoPrivKey(msg);
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetProofOfPossessionAgreeMac(PKMacValue macValue)
+ {
+ if (_popSigner != null || _popRaVerified != null || _popoPrivKey != null)
+ {
+ throw new InvalidOperationException("only one proof of possession allowed");
+ }
+
+ this._agreeMac = macValue;
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetProofOfPossessionRaVerified()
+ {
+ if (_popSigner != null || _popoPrivKey != null)
+ {
+ throw new InvalidOperationException("only one proof of possession allowed");
+ }
+
+ this._popRaVerified = DerNull.Instance;
+
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetAuthInfoPKMAC(PkMacFactory pkmacFactory, char[] password)
+ {
+ this._pkMacBuilder = pkmacFactory;
+ this._password = password;
+
+ return this;
+ }
+
+ public CertificateRequestMessageBuilder SetAuthInfoSender(X509Name sender)
+ {
+ return SetAuthInfoSender(new GeneralName(sender));
+ }
+
+ public CertificateRequestMessageBuilder SetAuthInfoSender(GeneralName sender)
+ {
+ this._sender = sender;
+ return this;
+ }
+
+ public CertificateRequestMessage Build()
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+
+ v.Add(new DerInteger(this._certReqId));
+
+ if (!this._extGenerator.IsEmpty)
+ {
+ this._templateBuilder.SetExtensions(_extGenerator.Generate());
+ }
+
+ v.Add(_templateBuilder.Build());
+
+ if (_controls.Count>0)
+ {
+ Asn1EncodableVector controlV = new Asn1EncodableVector();
+
+ foreach (Object item in _controls)
+ {
+ IControl control = (IControl) item;
+ controlV.Add(new AttributeTypeAndValue(control.Type, control.Value));
+ }
+
+ v.Add(new DerSequence(controlV));
+ }
+
+ CertRequest request = CertRequest.GetInstance(new DerSequence(v));
+
+ v = new Asn1EncodableVector();
+
+ v.Add(request);
+
+ if (_popSigner != null)
+ {
+ CertTemplate template = request.CertTemplate;
+
+ if (template.Subject == null || template.PublicKey == null)
+ {
+ SubjectPublicKeyInfo pubKeyInfo = request.CertTemplate.PublicKey;
+
+ ProofOfPossessionSigningKeyBuilder builder = new ProofOfPossessionSigningKeyBuilder(pubKeyInfo);
+
+ if (_sender != null)
+ {
+ builder.setSender(_sender);
+ }
+ else
+ {
+ // PkMa pkmacGenerator = new PKMACValueGenerator(_pkmacBuilder);
+
+ builder.setPublicKeyMac(_pkMacBuilder, _password);
+ }
+
+ v.Add(new ProofOfPossession(builder.build(_popSigner)));
+ }
+ else
+ {
+ ProofOfPossessionSigningKeyBuilder builder = new ProofOfPossessionSigningKeyBuilder(request);
+
+ v.Add(new ProofOfPossession(builder.build(_popSigner)));
+ }
+ }
+ else if (_popoPrivKey != null)
+ {
+ v.Add(new ProofOfPossession(_popoType, _popoPrivKey));
+ }
+ else if (_agreeMac != null)
+ {
+ v.Add(new ProofOfPossession(ProofOfPossession.TYPE_KEY_AGREEMENT,
+ PopoPrivKey.GetInstance(new DerTaggedObject(false, PopoPrivKey.agreeMAC, _agreeMac),true )));
+
+ }
+ else if (_popRaVerified != null)
+ {
+ v.Add(new ProofOfPossession());
+ }
+
+ return new CertificateRequestMessage(CertReqMsg.GetInstance(new DerSequence(v)));
+ }
+ }
+}
diff --git a/crypto/src/crmf/CrmfException.cs b/crypto/src/crmf/CrmfException.cs
new file mode 100644
index 000000000..c80f480b7
--- /dev/null
+++ b/crypto/src/crmf/CrmfException.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class CrmfException : Exception
+ {
+ public CrmfException()
+ {
+ }
+
+ public CrmfException(string message) : base(message)
+ {
+ }
+
+ public CrmfException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected CrmfException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
diff --git a/crypto/src/crmf/IControl.cs b/crypto/src/crmf/IControl.cs
new file mode 100644
index 000000000..8f986168c
--- /dev/null
+++ b/crypto/src/crmf/IControl.cs
@@ -0,0 +1,63 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+
+ public interface IControl
+ {
+ DerObjectIdentifier Type { get; }
+
+ Asn1Encodable Value { get; }
+ }
+
+
+ public class Controls
+ : Asn1Encodable
+ {
+ private readonly Asn1Sequence content;
+
+ private Controls(Asn1Sequence seq)
+ {
+ content = seq;
+ }
+
+ public static Controls GetInstance(object obj)
+ {
+ if (obj is Controls)
+ return (Controls)obj;
+
+ if (obj is Asn1Sequence)
+ return new Controls((Asn1Sequence)obj);
+
+ throw new ArgumentException("Invalid object: " + Platform.GetTypeName(obj), "obj");
+ }
+
+ public Controls(params AttributeTypeAndValue[] atvs)
+ {
+ content = new DerSequence(atvs);
+ }
+
+ public virtual AttributeTypeAndValue[] ToAttributeTypeAndValueArray()
+ {
+ AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.Count];
+ for (int i = 0; i != result.Length; ++i)
+ {
+ result[i] = AttributeTypeAndValue.GetInstance(content[i]);
+ }
+ return result;
+ }
+
+ /**
+ * <pre>
+ * Controls ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+ * </pre>
+ * @return a basic ASN.1 object representation.
+ */
+ public override Asn1Object ToAsn1Object()
+ {
+ return content;
+ }
+ }
+}
diff --git a/crypto/src/crmf/PkiArchiveControl.cs b/crypto/src/crmf/PkiArchiveControl.cs
new file mode 100644
index 000000000..ec8fb7671
--- /dev/null
+++ b/crypto/src/crmf/PkiArchiveControl.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Cms;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class PkiArchiveControl:IControl
+ {
+ public static readonly int encryptedPrivKey = PkiArchiveOptions.encryptedPrivKey;
+ public static readonly int keyGenParameters = PkiArchiveOptions.keyGenParameters;
+ public static readonly int archiveRemGenPrivKey = PkiArchiveOptions.archiveRemGenPrivKey;
+
+ private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_pkiArchiveOptions;
+
+ private readonly PkiArchiveOptions pkiArchiveOptions;
+
+ public PkiArchiveControl(PkiArchiveOptions pkiArchiveOptions)
+ {
+ this.pkiArchiveOptions = pkiArchiveOptions;
+ }
+
+ public DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+
+ public Asn1Encodable Value
+ {
+ get { return pkiArchiveOptions; }
+ }
+
+ public int ArchiveType
+ {
+ get { return pkiArchiveOptions.Type; }
+ }
+
+ public bool EnvelopedData
+ {
+ get
+ {
+ EncryptedKey encKey = EncryptedKey.GetInstance(pkiArchiveOptions.Value);
+ return !encKey.IsEncryptedValue;
+ }
+ }
+
+ public CmsEnvelopedData GetEnvelopedData()
+ {
+ try
+ {
+ EncryptedKey encKey = EncryptedKey.GetInstance(pkiArchiveOptions.Value);
+ EnvelopedData data = Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(encKey.Value);
+
+ return new CmsEnvelopedData(new ContentInfo(CmsObjectIdentifiers.EnvelopedData, data));
+ }
+ catch (CmsException e)
+ {
+ throw new CrmfException("CMS parsing error: " + e.Message, e);
+ }
+ catch (Exception e)
+ {
+ throw new CrmfException("CRMF parsing error: "+e.Message, e);
+ }
+ }
+
+ }
+}
diff --git a/crypto/src/crmf/RegTokenControl.cs b/crypto/src/crmf/RegTokenControl.cs
new file mode 100644
index 000000000..b53ce1922
--- /dev/null
+++ b/crypto/src/crmf/RegTokenControl.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Org.BouncyCastle.Crmf;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Crmf
+{
+ public class RegTokenControl:IControl
+ {
+ private static readonly DerObjectIdentifier type = CrmfObjectIdentifiers.id_regCtrl_regToken;
+
+ private readonly DerUtf8String token;
+
+ public RegTokenControl(DerUtf8String token)
+ {
+ this.token = token;
+ }
+
+ public RegTokenControl(String token)
+ {
+ this.token = new DerUtf8String(token);
+ }
+
+ public DerObjectIdentifier Type
+ {
+ get { return type; }
+ }
+ public Asn1Encodable Value
+ {
+ get { return token; }
+ }
+ }
+}
|