Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 53 additions & 5 deletions CryptoLib.Tests/src/Crypto/PssTests.pas
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ TTestPss = class(TCryptoLibAlgorithmTestCase)
procedure DoSignerUtilitiesSha256;
procedure DoSignerUtilitiesSha384;
procedure DoSignerUtilitiesSha512;
procedure DoSignerUtilitiesExtraPss;
procedure DoRawSignerTest;

published
Expand All @@ -111,6 +112,7 @@ TTestPss = class(TCryptoLibAlgorithmTestCase)
procedure TestSignerUtilitiesSha256;
procedure TestSignerUtilitiesSha384;
procedure TestSignerUtilitiesSha512;
procedure TestSignerUtilitiesExtraPss;
procedure TestRawSigner;

end;
Expand Down Expand Up @@ -312,7 +314,7 @@ procedure TTestPss.DoSignerUtilitiesSha1;
begin
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create(), 2048, 100);
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

Expand Down Expand Up @@ -344,7 +346,7 @@ procedure TTestPss.DoSignerUtilitiesSha256;
begin
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create(), 2048, 100);
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

Expand Down Expand Up @@ -384,7 +386,7 @@ procedure TTestPss.DoSignerUtilitiesSha384;
begin
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create(), 2048, 100);
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

Expand Down Expand Up @@ -416,7 +418,7 @@ procedure TTestPss.DoSignerUtilitiesSha512;
begin
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create(), 2048, 100);
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

Expand All @@ -437,6 +439,47 @@ procedure TTestPss.DoSignerUtilitiesSha512;
CheckTrue(verified, 'PSS SHA-512 signature verification failed');
end;

procedure TTestPss.DoSignerUtilitiesExtraPss;
const
AlgNames: array [0 .. 6] of String = ('RIPEMD128withRSAandMGF1',
'RIPEMD160withRSAandMGF1', 'RIPEMD256withRSAandMGF1',
'SHA3-224withRSAandMGF1', 'SHA3-256withRSAandMGF1',
'SHA3-384withRSAandMGF1', 'SHA3-512withRSAandMGF1');
var
kpGen: IRsaKeyPairGenerator;
kpParams: IRsaKeyGenerationParameters;
keyPair: IAsymmetricCipherKeyPair;
signer: ISigner;
&message, signature: TCryptoLibByteArray;
i: Integer;
begin
// One 2048-bit key is large enough for every RIPEMD/SHA3 salt length here
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

&message := TConverters.ConvertStringToBytes('Test PSS RIPEMD/SHA3 signature',
TEncoding.UTF8);

for i := Low(AlgNames) to High(AlgNames) do
begin
signer := TSignerUtilities.GetSigner(AlgNames[i]);
signer.Init(True, keyPair.Private);
signer.BlockUpdate(&message, 0, System.Length(&message));
signature := signer.GenerateSignature();

CheckTrue(System.Length(signature) > 0,
Format('PSS %s signature is empty', [AlgNames[i]]));

signer.Init(False, keyPair.Public);
signer.BlockUpdate(&message, 0, System.Length(&message));
CheckTrue(signer.VerifySignature(signature),
Format('PSS %s signature verification failed', [AlgNames[i]]));
end;
end;

procedure TTestPss.DoRawSignerTest;
var
kpGen: IRsaKeyPairGenerator;
Expand All @@ -449,7 +492,7 @@ procedure TTestPss.DoRawSignerTest;
begin
kpGen := TRsaKeyPairGenerator.Create();
kpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(17), TSecureRandom.Create(), 1024, 100);
TBigInteger.ValueOf(17), TSecureRandom.Create() as ISecureRandom, 1024, 100);
kpGen.Init(kpParams);
keyPair := kpGen.GenerateKeyPair();

Expand Down Expand Up @@ -531,6 +574,11 @@ procedure TTestPss.TestSignerUtilitiesSha512;
DoSignerUtilitiesSha512;
end;

procedure TTestPss.TestSignerUtilitiesExtraPss;
begin
DoSignerUtilitiesExtraPss;
end;

procedure TTestPss.TestRawSigner;
begin
DoRawSignerTest;
Expand Down
51 changes: 51 additions & 0 deletions CryptoLib.Tests/src/X509/X509CertGenTests.pas
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ interface
ClpIX509Generators,
ClpAsn1SignatureFactory,
ClpISignatureFactory,
ClpIRsaGenerators,
ClpRsaGenerators,
ClpISecureRandom,
ClpSecureRandom,
ClpIAsymmetricCipherKeyPair,
ClpIRsaParameters,
ClpRsaParameters,
ClpIDsaParameters,
ClpIECParameters,
ClpECParameters,
Expand Down Expand Up @@ -80,6 +86,7 @@ TX509CertGenTest = class(TCryptoLibAlgorithmTestCase)
procedure TestCreationRSA;
procedure TestCreationDSA;
procedure TestCreationECDSA;
procedure TestCreationRsaPss;

end;

Expand Down Expand Up @@ -235,6 +242,50 @@ procedure TX509CertGenTest.TestCreationECDSA;
Fail('wrong number of oids');
end;

procedure TX509CertGenTest.TestCreationRsaPss;
const
AlgNames: array [0 .. 6] of String = ('RIPEMD128withRSAandMGF1',
'RIPEMD160withRSAandMGF1', 'RIPEMD256withRSAandMGF1',
'SHA3-224withRSAandMGF1', 'SHA3-256withRSAandMGF1',
'SHA3-384withRSAandMGF1', 'SHA3-512withRSAandMGF1');
var
LKpGen: IRsaKeyPairGenerator;
LKpParams: IRsaKeyGenerationParameters;
LKeyPair: IAsymmetricCipherKeyPair;
LCertGen: IX509V3CertificateGenerator;
LName: IX509Name;
LCert: IX509Certificate;
LSigner: ISignatureFactory;
LUtc: TDateTime;
I: Int32;
begin
// 2048-bit key is large enough for every RIPEMD/SHA3 PSS salt length here
LKpGen := TRsaKeyPairGenerator.Create();
LKpParams := TRsaKeyGenerationParameters.Create(
TBigInteger.ValueOf(65537), TSecureRandom.Create() as ISecureRandom, 2048, 100);
LKpGen.Init(LKpParams);
LKeyPair := LKpGen.GenerateKeyPair();
LName := CreateX509Name;
LUtc := Now.ToUniversalTime();

for I := Low(AlgNames) to High(AlgNames) do
begin
LCertGen := TX509V3CertificateGenerator.Create;
LCertGen.SetSerialNumber(TBigInteger.One);
LCertGen.SetIssuerDN(LName);
LCertGen.SetNotBeforeUtc(IncDay(LUtc, -1));
LCertGen.SetNotAfterUtc(IncDay(LUtc, 1));
LCertGen.SetSubjectDN(LName);
LCertGen.SetPublicKey(LKeyPair.Public);

LSigner := TAsn1SignatureFactory.Create(AlgNames[I], LKeyPair.Private, nil);
LCert := LCertGen.Generate(LSigner);

LCert.CheckValidity();
LCert.Verify(LKeyPair.Public);
end;
end;

initialization

{$IFDEF FPC}
Expand Down
38 changes: 38 additions & 0 deletions CryptoLib/src/Asn1/X509/ClpX509SignatureUtilities.pas
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ implementation
class constructor TX509SignatureUtilities.Create;
var
LSha1AlgId, LSha224AlgId, LSha256AlgId, LSha384AlgId, LSha512AlgId: IAlgorithmIdentifier;
LSha3_224AlgId, LSha3_256AlgId, LSha3_384AlgId, LSha3_512AlgId: IAlgorithmIdentifier;
LRipeMD128AlgId, LRipeMD160AlgId, LRipeMD256AlgId: IAlgorithmIdentifier;
LParams: IMlDsaParameters;
LSlhParams: ISlhDsaParameters;
begin
Expand Down Expand Up @@ -158,6 +160,13 @@ implementation
FAlgorithms.Add('SHA256WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA384WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA512WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA3-224WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA3-256WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA3-384WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('SHA3-512WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('RIPEMD128WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('RIPEMD160WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
FAlgorithms.Add('RIPEMD256WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);

// RIPEMD algorithms
FAlgorithms.Add('RIPEMD160WITHRSAENCRYPTION', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
Expand Down Expand Up @@ -265,6 +274,27 @@ implementation
LSha512AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha512, TDerNull.Instance);
FExParams.Add('SHA512WITHRSAANDMGF1', CreatePssParams(LSha512AlgId, 64));

LSha3_224AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha3_224, TDerNull.Instance);
FExParams.Add('SHA3-224WITHRSAANDMGF1', CreatePssParams(LSha3_224AlgId, 28));

LSha3_256AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha3_256, TDerNull.Instance);
FExParams.Add('SHA3-256WITHRSAANDMGF1', CreatePssParams(LSha3_256AlgId, 32));

LSha3_384AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha3_384, TDerNull.Instance);
FExParams.Add('SHA3-384WITHRSAANDMGF1', CreatePssParams(LSha3_384AlgId, 48));

LSha3_512AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha3_512, TDerNull.Instance);
FExParams.Add('SHA3-512WITHRSAANDMGF1', CreatePssParams(LSha3_512AlgId, 64));

LRipeMD128AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD128, TDerNull.Instance);
FExParams.Add('RIPEMD128WITHRSAANDMGF1', CreatePssParams(LRipeMD128AlgId, 16));

LRipeMD160AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD160, TDerNull.Instance);
FExParams.Add('RIPEMD160WITHRSAANDMGF1', CreatePssParams(LRipeMD160AlgId, 20));

LRipeMD256AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD256, TDerNull.Instance);
FExParams.Add('RIPEMD256WITHRSAANDMGF1', CreatePssParams(LRipeMD256AlgId, 32));

//
// DSA with SHA3
//
Expand Down Expand Up @@ -333,6 +363,14 @@ class function TX509SignatureUtilities.GetDigestName(const ADigestAlgOid: IDerOb
Result := 'SHA512(224)'
else if TNistObjectIdentifiers.IdSha512_256.Equals(ADigestAlgOid) then
Result := 'SHA512(256)'
else if TNistObjectIdentifiers.IdSha3_224.Equals(ADigestAlgOid) then
Result := 'SHA3-224'
else if TNistObjectIdentifiers.IdSha3_256.Equals(ADigestAlgOid) then
Result := 'SHA3-256'
else if TNistObjectIdentifiers.IdSha3_384.Equals(ADigestAlgOid) then
Result := 'SHA3-384'
else if TNistObjectIdentifiers.IdSha3_512.Equals(ADigestAlgOid) then
Result := 'SHA3-512'
else if TTeleTrusTObjectIdentifiers.RipeMD128.Equals(ADigestAlgOid) then
Result := 'RIPEMD128'
else if TTeleTrusTObjectIdentifiers.RipeMD160.Equals(ADigestAlgOid) then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ implementation
var
LSha1AlgId, LSha224AlgId, LSha256AlgId, LSha384AlgId, LSha512AlgId: IAlgorithmIdentifier;
LSha3_224AlgId, LSha3_256AlgId, LSha3_384AlgId, LSha3_512AlgId: IAlgorithmIdentifier;
LRipeMD128AlgId, LRipeMD160AlgId, LRipeMD256AlgId: IAlgorithmIdentifier;
LParams: IMlDsaParameters;
LSlhParams: ISlhDsaParameters;
begin
Expand Down Expand Up @@ -154,6 +155,9 @@ implementation
AddAlgorithm('SHA3-256WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('SHA3-384WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('SHA3-512WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('RIPEMD128WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('RIPEMD160WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('RIPEMD256WITHRSAANDMGF1', TPkcsObjectIdentifiers.IdRsassaPss);
AddAlgorithm('RIPEMD160WITHRSAENCRYPTION', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
AddAlgorithm('RIPEMD160WITHRSA', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
AddAlgorithm('RIPEMD128WITHRSAENCRYPTION', TTeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
Expand Down Expand Up @@ -346,6 +350,15 @@ implementation
LSha3_512AlgId := TAlgorithmIdentifier.Create(TNistObjectIdentifiers.IdSha3_512, TDerNull.Instance);
AddParameters('SHA3-512WITHRSAANDMGF1', CreatePssParams(LSha3_512AlgId, 64));

LRipeMD128AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD128, TDerNull.Instance);
AddParameters('RIPEMD128WITHRSAANDMGF1', CreatePssParams(LRipeMD128AlgId, 16));

LRipeMD160AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD160, TDerNull.Instance);
AddParameters('RIPEMD160WITHRSAANDMGF1', CreatePssParams(LRipeMD160AlgId, 20));

LRipeMD256AlgId := TAlgorithmIdentifier.Create(TTeleTrusTObjectIdentifiers.RipeMD256, TDerNull.Instance);
AddParameters('RIPEMD256WITHRSAANDMGF1', CreatePssParams(LRipeMD256AlgId, 32));

//
// digests
//
Expand Down
36 changes: 14 additions & 22 deletions CryptoLib/src/Crypto/Signers/ClpPssSigner.pas
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface
ClpParameterUtilities,
ClpBigInteger,
ClpArrayUtilities,
ClpBinaryPrimitives,
ClpCryptoLibTypes,
ClpCryptoLibExceptions;

Expand Down Expand Up @@ -73,7 +74,6 @@ TPssSigner = class(TInterfacedObject, ISigner, IPssSigner)
FTrailer: Byte;

procedure ClearBlock(const ABlock: TCryptoLibByteArray);
procedure ItoOSP(AI: Int32; const ASP: TCryptoLibByteArray);
function MaskGeneratorFunction(const AZ: TCryptoLibByteArray;
AZOff, AZLen, ALength: Int32): TCryptoLibByteArray;
function MaskGeneratorFunction1(const AZ: TCryptoLibByteArray;
Expand Down Expand Up @@ -465,14 +465,6 @@ procedure TPssSigner.Reset;
FContentDigest1.Reset();
end;

procedure TPssSigner.ItoOSP(AI: Int32; const ASP: TCryptoLibByteArray);
begin
ASP[0] := Byte(UInt32(AI) shr 24);
ASP[1] := Byte(UInt32(AI) shr 16);
ASP[2] := Byte(UInt32(AI) shr 8);
ASP[3] := Byte(UInt32(AI) shr 0);
end;

function TPssSigner.MaskGeneratorFunction(const AZ: TCryptoLibByteArray;
AZOff, AZLen, ALength: Int32): TCryptoLibByteArray;
var
Expand All @@ -496,37 +488,37 @@ function TPssSigner.MaskGeneratorFunction1(const AZ: TCryptoLibByteArray;
AZOff, AZLen, ALength: Int32): TCryptoLibByteArray;
var
LMask, LHashBuf, LC: TCryptoLibByteArray;
LCounter: Int32;
LCounter, LPos: Int32;
begin
SetLength(LMask, ALength);
SetLength(LHashBuf, FMgfhLen);
SetLength(LC, 4);
LCounter := 0;
LPos := 0;

FMgfDigest.Reset();

while LCounter < (ALength div FMgfhLen) do
// full blocks are finalized straight into the mask; only the tail needs a temp buffer
while LPos <= ALength - FMgfhLen do
begin
ItoOSP(LCounter, LC);
TBinaryPrimitives.WriteUInt32BigEndian(LC, 0, UInt32(LCounter));
Inc(LCounter);

FMgfDigest.BlockUpdate(AZ, AZOff, AZLen);
FMgfDigest.BlockUpdate(LC, 0, System.Length(LC));
FMgfDigest.DoFinal(LHashBuf, 0);

System.Move(LHashBuf[0], LMask[LCounter * FMgfhLen], System.Length(LHashBuf));
Inc(LCounter);
FMgfDigest.DoFinal(LMask, LPos);
Inc(LPos, FMgfhLen);
end;

if (LCounter * FMgfhLen) < ALength then
if LPos < ALength then
begin
ItoOSP(LCounter, LC);
TBinaryPrimitives.WriteUInt32BigEndian(LC, 0, UInt32(LCounter));

FMgfDigest.BlockUpdate(AZ, AZOff, AZLen);
FMgfDigest.BlockUpdate(LC, 0, System.Length(LC));
FMgfDigest.DoFinal(LHashBuf, 0);

System.Move(LHashBuf[0], LMask[LCounter * FMgfhLen],
System.Length(LMask) - (LCounter * FMgfhLen));
SetLength(LHashBuf, FMgfhLen);
FMgfDigest.DoFinal(LHashBuf, 0);
System.Move(LHashBuf[0], LMask[LPos], System.Length(LMask) - LPos);
end;

Result := LMask;
Expand Down
Loading