Skip to content

Commit

Permalink
Add ASN1 decoding of PBES2 algorithm in encrypted data
Browse files Browse the repository at this point in the history
  • Loading branch information
fmarco76 committed Aug 5, 2022
1 parent 1143301 commit 5387c49
Show file tree
Hide file tree
Showing 3 changed files with 322 additions and 10 deletions.
44 changes: 34 additions & 10 deletions base/src/main/java/org/mozilla/jss/pkcs7/EncryptedContentInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier;
import org.mozilla.jss.pkix.primitive.PBEParameter;
import org.mozilla.jss.pkix.primitive.PBES2Params;
import org.mozilla.jss.pkix.primitive.PBKDF2Params;
import org.mozilla.jss.util.Password;

/**
Expand Down Expand Up @@ -236,27 +238,49 @@ public static EncryptedContentInfo createCRSCompatibleEncryptedContentInfo(OBJEC
}

// get the key gen parameters
AlgorithmIdentifier algid = contentEncryptionAlgorithm;
KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() );
KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( contentEncryptionAlgorithm.getOID() );
if( !(kgAlg instanceof PBEAlgorithm) ) {
throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a"+
" PBE algorithm");
}
ASN1Value params = algid.getParameters();
ASN1Value params = contentEncryptionAlgorithm.getParameters();
if( params == null ) {
throw new InvalidAlgorithmParameterException(
"PBE algorithms require parameters");
}
PBEParameter pbeParams;
if( params instanceof PBEParameter) {
pbeParams = (PBEParameter) params;
} else {
byte[] salt = null;
int iterations = 0;
if(!kgAlg.toOID().equals(PBEAlgorithm.PBE_PKCS5_PBES2.toOID())) {
PBEParameter pbeParams;
if( params instanceof PBEParameter) {
pbeParams = (PBEParameter) params;
} else {
byte[] encodedParams = ASN1Util.encode(params);
pbeParams = (PBEParameter)
ASN1Util.decode( PBEParameter.getTemplate(), encodedParams );
}
salt = pbeParams.getSalt();
iterations = pbeParams.getIterations();
}
else {
byte[] encodedParams = ASN1Util.encode(params);
pbeParams = (PBEParameter)
ASN1Util.decode( PBEParameter.getTemplate(), encodedParams );
PBES2Params pbe2Params = (PBES2Params)
ASN1Util.decode( PBES2Params.getTemplate(), encodedParams);
AlgorithmIdentifier keyDerivationFunc = pbe2Params.getKeyDerivationFunc();
if(!keyDerivationFunc.getOID().equals(PBEAlgorithm.PBE_PKCS5_PBKDF2.toOID())) {
throw new InvalidAlgorithmParameterException("PBEs2 requires a PBKDF2 keyDerivationFunc"
+ keyDerivationFunc.getOID().toDottedString());
}
byte[] encodedPBKParams = ASN1Util.encode(keyDerivationFunc.getParameters());
PBKDF2Params pbkParams = (PBKDF2Params) ASN1Util.decode(
PBKDF2Params.getTemplate(), encodedPBKParams);
salt = pbkParams.getSalt();
iterations = pbkParams.getIterations();
}


PBEKeyGenParams kgp = new PBEKeyGenParams(pass,
pbeParams.getSalt(), pbeParams.getIterations() );
salt, iterations );

try {
// compute the key and IV
Expand Down
114 changes: 114 additions & 0 deletions base/src/main/java/org/mozilla/jss/pkix/primitive/PBES2Params.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.jss.pkix.primitive;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.mozilla.jss.asn1.ASN1Template;
import org.mozilla.jss.asn1.ASN1Value;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.Tag;

/**
* PKCS #5 <i>PBES2Parameter</i>
*/
public class PBES2Params implements ASN1Value {

///////////////////////////////////////////////////////////////////////
// members and member access
///////////////////////////////////////////////////////////////////////
private AlgorithmIdentifier keyDerivationFunc;
private AlgorithmIdentifier encryptionScheme;
private SEQUENCE sequence;

public AlgorithmIdentifier getKeyDerivationFunc() {
return keyDerivationFunc;
}

public AlgorithmIdentifier getEncryptionScheme() {
return encryptionScheme;
}


///////////////////////////////////////////////////////////////////////
// constructors
///////////////////////////////////////////////////////////////////////


public PBES2Params(AlgorithmIdentifier keyDerivationFunc, AlgorithmIdentifier encryptionScheme) {
this.keyDerivationFunc = keyDerivationFunc;
this.encryptionScheme = encryptionScheme;
sequence = new SEQUENCE();
sequence.addElement( keyDerivationFunc );
sequence.addElement( encryptionScheme );
}

///////////////////////////////////////////////////////////////////////
// DER encoding
///////////////////////////////////////////////////////////////////////

private static final Tag TAG = SEQUENCE.TAG;
@Override
public Tag getTag() {
return TAG;
}

@Override
public void encode(OutputStream ostream) throws IOException {
sequence.encode(ostream);
}

@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
sequence.encode(implicitTag, ostream);
}


private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}

/**
* A template class for decoding a PBES2Params.
*/
public static class Template implements ASN1Template {

private SEQUENCE.Template seqt;

public Template() {
seqt = new SEQUENCE.Template();
seqt.addElement( AlgorithmIdentifier.getTemplate() );
seqt.addElement( AlgorithmIdentifier.getTemplate() );
}

@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}

@Override
public ASN1Value decode(InputStream istream)
throws InvalidBERException, IOException
{
return decode(TAG, istream);
}

@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws InvalidBERException, IOException
{
SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream);

return new PBES2Params( (AlgorithmIdentifier) seq.elementAt(0),
(AlgorithmIdentifier) seq.elementAt(1) );
}
}
}
174 changes: 174 additions & 0 deletions base/src/main/java/org/mozilla/jss/pkix/primitive/PBKDF2Params.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.jss.pkix.primitive;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.mozilla.jss.asn1.ASN1Template;
import org.mozilla.jss.asn1.ASN1Value;
import org.mozilla.jss.asn1.CHOICE;
import org.mozilla.jss.asn1.INTEGER;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.OCTET_STRING;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.Tag;

/**
* PKCS #5 <i>PBKDF2-Params</i>.
*/
public class PBKDF2Params implements ASN1Value {

///////////////////////////////////////////////////////////////////////
// members and member access
///////////////////////////////////////////////////////////////////////
private byte[] salt;
private AlgorithmIdentifier otherSource;
private int iterations;
private int keyLength;
private AlgorithmIdentifier prf;
private SEQUENCE sequence;

public byte[] getSalt() {
return salt;
}

public int getIterations() {
return iterations;
}

public AlgorithmIdentifier getOtherSource() {
return otherSource;
}

public int getKeyLength() {
return keyLength;
}


///////////////////////////////////////////////////////////////////////
// constructors
///////////////////////////////////////////////////////////////////////

/**
* Creates a PBKDF2Params from a salt and iteration count
*/
public PBKDF2Params(byte[] salt, AlgorithmIdentifier otherSource,
int iterations, int keyLength, AlgorithmIdentifier prf) {
this.salt = salt;
this.otherSource = otherSource;
this.iterations = iterations;
this.keyLength = keyLength;
this.prf = prf;
sequence = new SEQUENCE();
if(salt!=null) {
sequence.addElement( new OCTET_STRING(salt) );
}
else {
sequence.addElement(otherSource);
}
sequence.addElement( new INTEGER(iterations) );
if(keyLength>0) {
sequence.addElement(new INTEGER(keyLength));
}
sequence.addElement(prf);
}

/**
* Creates a PBKDF2Params from a salt and iteration count
*/
public PBKDF2Params(OCTET_STRING salt, AlgorithmIdentifier otherSource,
INTEGER iterations, INTEGER keyLength, AlgorithmIdentifier prf) {
this( salt.toByteArray(), otherSource, iterations.intValue(),
keyLength.intValue(), prf);
}

///////////////////////////////////////////////////////////////////////
// DER encoding
///////////////////////////////////////////////////////////////////////

private static final Tag TAG = SEQUENCE.TAG;
@Override
public Tag getTag() {
return TAG;
}

@Override
public void encode(OutputStream ostream) throws IOException {
sequence.encode(ostream);
}

@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
sequence.encode(implicitTag, ostream);
}


private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}

/**
* A template class for decoding a PBKDF2Params.
*/
public static class Template implements ASN1Template {

private SEQUENCE.Template seqt;

public Template() {
seqt = new SEQUENCE.Template();

CHOICE.Template salt = CHOICE.getTemplate();
salt.addElement(OCTET_STRING.getTemplate());
salt.addElement(AlgorithmIdentifier.getTemplate());

seqt.addElement(salt);
seqt.addElement(INTEGER.getTemplate());
seqt.addOptionalElement(INTEGER.getTemplate());
seqt.addElement(AlgorithmIdentifier.getTemplate());
}

@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}

@Override
public ASN1Value decode(InputStream istream)
throws InvalidBERException, IOException
{
return decode(TAG, istream);
}

@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws InvalidBERException, IOException
{
OCTET_STRING specified = null;
AlgorithmIdentifier otherSource = null;

SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream);

CHOICE salt = (CHOICE) seq.elementAt(0);
if (salt.getValue() instanceof OCTET_STRING saltValue) {
specified = saltValue;
}

if (salt.getValue() instanceof AlgorithmIdentifier saltSource) {
otherSource = saltSource;
}

return new PBKDF2Params( specified,
otherSource,
(INTEGER) seq.elementAt(1),
(INTEGER) seq.elementAt(2),
(AlgorithmIdentifier) seq.elementAt(3));
}
}
}

0 comments on commit 5387c49

Please sign in to comment.