From b9d1dc564ef069cb5566d1f42d9197ed8335deef Mon Sep 17 00:00:00 2001 From: David Lee Date: Wed, 10 Aug 2011 07:36:50 -0700 Subject: [PATCH 1/4] Implement PKCS7#type= --- src/java/org/jruby/ext/openssl/PKCS7.java | 8 ++++--- .../org/jruby/ext/openssl/impl/PKCS7.java | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/java/org/jruby/ext/openssl/PKCS7.java b/src/java/org/jruby/ext/openssl/PKCS7.java index ab4a6de..21318ec 100644 --- a/src/java/org/jruby/ext/openssl/PKCS7.java +++ b/src/java/org/jruby/ext/openssl/PKCS7.java @@ -260,6 +260,7 @@ public IRubyObject getData() { public IRubyObject _initialize(IRubyObject[] args) { IRubyObject arg = null; if(Arity.checkArgumentCount(getRuntime(), args, 0, 1) == 0) { + p7 = new org.jruby.ext.openssl.impl.PKCS7(); return this; } arg = args[0]; @@ -288,9 +289,10 @@ public IRubyObject initialize_copy(IRubyObject obj) { } @JRubyMethod(name="type=") - public IRubyObject set_type(IRubyObject obj) { - System.err.println("WARNING: unimplemented method called PKCS7#type="); - return getRuntime().getNil(); + public IRubyObject set_type(IRubyObject obj) throws PKCS7Exception { + String str = obj.convertToString().asJavaString(); + p7.setTypeByName(str); + return obj; } @JRubyMethod(name="type") diff --git a/src/java/org/jruby/ext/openssl/impl/PKCS7.java b/src/java/org/jruby/ext/openssl/impl/PKCS7.java index 4b4118c..8b2a206 100644 --- a/src/java/org/jruby/ext/openssl/impl/PKCS7.java +++ b/src/java/org/jruby/ext/openssl/impl/PKCS7.java @@ -493,6 +493,21 @@ public void decrypt(PrivateKey pkey, X509AuxCertificate cert, BIO data, int flag } } + public void setTypeByName(String type) throws PKCS7Exception { + if (TYPE_signed.equals(type)) + this.data = new PKCS7DataSigned(); + else if (TYPE_data.equals(type)) + this.data = new PKCS7DataData(); + else if (TYPE_signedAndEnveloped.equals(type)) + this.data = new PKCS7DataSignedAndEnveloped(); + else if (TYPE_enveloped.equals(type)) + this.data = new PKCS7DataEnveloped(); + else if (TYPE_encrypted.equals(type)) + this.data = new PKCS7DataEncrypted(); + else + throw new PKCS7Exception(F_PKCS7_SET_TYPE,R_UNSUPPORTED_CONTENT_TYPE); + } + /** c: PKCS7_set_type * */ @@ -1261,5 +1276,12 @@ public ASN1OctetString getOctetString() { } return null; } + + public final static String TYPE_signed = "signed"; + public final static String TYPE_encrypted = "encrypted"; + public final static String TYPE_enveloped = "enveloped"; + public final static String TYPE_signedAndEnveloped = "signedAndEnveloped"; + public final static String TYPE_data = "data"; + }// PKCS7 From 9dadbc17b05370f005acd6ad9ed6d4d498f30997 Mon Sep 17 00:00:00 2001 From: David Lee Date: Wed, 10 Aug 2011 07:38:11 -0700 Subject: [PATCH 2/4] Workaround strange case of split OctetStrings OctetString can be split into a Sequence of OctetStrings. Merge them back before passing to setEncData(). --- .../jruby/ext/openssl/impl/EncContent.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/java/org/jruby/ext/openssl/impl/EncContent.java b/src/java/org/jruby/ext/openssl/impl/EncContent.java index a2d8a03..ec12342 100644 --- a/src/java/org/jruby/ext/openssl/impl/EncContent.java +++ b/src/java/org/jruby/ext/openssl/impl/EncContent.java @@ -27,12 +27,14 @@ ***** END LICENSE BLOCK *****/ package org.jruby.ext.openssl.impl; +import java.util.Enumeration; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1OctetString; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DEREncodable; import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERTaggedObject; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; @@ -157,7 +159,26 @@ public static EncContent fromASN1(DEREncodable content) { ec.setAlgorithm(AlgorithmIdentifier.getInstance(sequence.getObjectAt(1))); if(sequence.size() > 2 && sequence.getObjectAt(2) instanceof DERTaggedObject && ((DERTaggedObject)(sequence.getObjectAt(2))).getTagNo() == 0) { DEREncodable ee = ((DERTaggedObject)(sequence.getObjectAt(2))).getObject(); - if(ee instanceof ASN1Sequence) { + if(ee instanceof ASN1Sequence) { // OctetString split into multiple OctetStrings in a Sequence + if (((ASN1Sequence)ee).size() > 0) { + // merge back into single OctetString + int totalSize = 0; + Enumeration e = ((ASN1Sequence)ee).getObjects(); + while (e.hasMoreElements()) { + byte[] octets = ((ASN1OctetString)e.nextElement()).getOctets(); + totalSize += octets.length; + } + byte[] data = new byte[totalSize]; + + int current = 0; + e = ((ASN1Sequence)ee).getObjects(); + while (e.hasMoreElements()) { + byte[] octets = ((ASN1OctetString)e.nextElement()).getOctets(); + System.arraycopy(octets, 0, data, current, octets.length); + current += octets.length; + } + ec.setEncData(new DEROctetString(data)); + } } else { ec.setEncData((ASN1OctetString)ee); } From ae87438f73abfbc8aefce38acd9693a54f159e35 Mon Sep 17 00:00:00 2001 From: David Lee Date: Wed, 10 Aug 2011 07:44:07 -0700 Subject: [PATCH 3/4] Support degenerate certs-only PKCS7 --- src/java/org/jruby/ext/openssl/impl/PKCS7.java | 6 ++++++ src/java/org/jruby/ext/openssl/impl/Signed.java | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/java/org/jruby/ext/openssl/impl/PKCS7.java b/src/java/org/jruby/ext/openssl/impl/PKCS7.java index 8b2a206..0ea229d 100644 --- a/src/java/org/jruby/ext/openssl/impl/PKCS7.java +++ b/src/java/org/jruby/ext/openssl/impl/PKCS7.java @@ -104,6 +104,12 @@ private void initiateWith(Integer nid, DEREncodable content) throws PKCS7Excepti this.data = PKCS7Data.fromASN1(nid, content); } + public static PKCS7 newEmpty() { + PKCS7 p7 = new PKCS7(); + p7.data = new PKCS7DataData(); + return p7; + } + /** * ContentInfo ::= SEQUENCE { * contentType ContentType, diff --git a/src/java/org/jruby/ext/openssl/impl/Signed.java b/src/java/org/jruby/ext/openssl/impl/Signed.java index 2adac0d..f4b2ea9 100644 --- a/src/java/org/jruby/ext/openssl/impl/Signed.java +++ b/src/java/org/jruby/ext/openssl/impl/Signed.java @@ -199,6 +199,9 @@ public ASN1Encodable asASN1() { ASN1EncodableVector vector = new ASN1EncodableVector(); vector.add(new DERInteger(version)); vector.add(digestAlgorithmsToASN1Set()); + if (contents == null) { + contents = PKCS7.newEmpty(); + } vector.add(contents.asASN1()); if (cert != null && cert.size() > 0) { if (cert.size() > 1) { From f88f3a8ff968bc199ef6910e31f9f800583d4397 Mon Sep 17 00:00:00 2001 From: David Lee Date: Wed, 10 Aug 2011 07:45:26 -0700 Subject: [PATCH 4/4] CertificationRequestInfo attribute can be a Sequence --- src/java/org/jruby/ext/openssl/Request.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/java/org/jruby/ext/openssl/Request.java b/src/java/org/jruby/ext/openssl/Request.java index 9d350a1..cf152c0 100644 --- a/src/java/org/jruby/ext/openssl/Request.java +++ b/src/java/org/jruby/ext/openssl/Request.java @@ -138,9 +138,20 @@ public Object call() throws GeneralSecurityException { } ASN1Set in_attrs = req.getCertificationRequestInfo().getAttributes(); for(Enumeration enm = in_attrs.getObjects();enm.hasMoreElements();) { - DERSet obj = (DERSet)enm.nextElement(); - for(Enumeration enm2 = obj.getObjects();enm2.hasMoreElements();) { - DERSequence val = (DERSequence)enm2.nextElement(); + Enumeration enm2; + Object next = enm.nextElement(); + if (next instanceof DERSet) { + enm2 = ((DERSet)next).getObjects(); + while(enm2.hasMoreElements()) { + DERSequence val = (DERSequence)enm2.nextElement(); + DERObjectIdentifier v0 = (DERObjectIdentifier)val.getObjectAt(0); + DERObject v1 = (DERObject)val.getObjectAt(1); + IRubyObject a1 = getRuntime().newString(ASN1.getSymLookup(getRuntime()).get(v0)); + IRubyObject a2 = ASN1.decode(getRuntime().getClassFromPath("OpenSSL::ASN1"), RubyString.newString(getRuntime(), v1.getDEREncoded())); + add_attribute(Utils.newRubyInstance(getRuntime(), "OpenSSL::X509::Attribute", new IRubyObject[] { a1, a2 })); + } + } else if (next instanceof DERSequence) { + DERSequence val = (DERSequence)next; DERObjectIdentifier v0 = (DERObjectIdentifier)val.getObjectAt(0); DERObject v1 = (DERObject)val.getObjectAt(1); IRubyObject a1 = getRuntime().newString(ASN1.getSymLookup(getRuntime()).get(v0));