Skip to content

Commit

Permalink
Merge pull request #1793 from dotpaul/fixes/1774-duplicate-cryptograp…
Browse files Browse the repository at this point in the history
…hy-codes

Fix issue 1774 for duplicate cryptography codes

Consolidated cryptography rules from NetFramework and NetCore into NetCore.
  • Loading branch information
dotpaul authored Aug 29, 2018
2 parents 986bfff + 405cde4 commit 100d223
Show file tree
Hide file tree
Showing 40 changed files with 2,788 additions and 2,947 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,65 @@ namespace Microsoft.NetCore.Analyzers.Security
{
public abstract class DoNotUseInsecureCryptographicAlgorithmsAnalyzer : DiagnosticAnalyzer
{
internal const string DoNotUseWeakCryptographicRuleId = "CA5350";
internal const string DoNotUseBrokenCryptographicRuleId = "CA5351";

private static readonly LocalizableString s_localizableDoNotUseMD5Title = new LocalizableResourceString(nameof(SystemSecurityCryptographyResources.DoNotUseMD5), SystemSecurityCryptographyResources.ResourceManager, typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseMD5Description = new LocalizableResourceString(nameof(SystemSecurityCryptographyResources.DoNotUseMD5Description), SystemSecurityCryptographyResources.ResourceManager, typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseSHA1Title = new LocalizableResourceString(nameof(SystemSecurityCryptographyResources.DoNotUseSHA1), SystemSecurityCryptographyResources.ResourceManager, typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseSHA1Description = new LocalizableResourceString(nameof(SystemSecurityCryptographyResources.DoNotUseSHA1Description), SystemSecurityCryptographyResources.ResourceManager, typeof(SystemSecurityCryptographyResources));

internal static DiagnosticDescriptor DoNotUseMD5SpecificRule = CreateDiagnosticDescriptor(DoNotUseBrokenCryptographicRuleId,
s_localizableDoNotUseMD5Title,
s_localizableDoNotUseMD5Description);

internal static DiagnosticDescriptor DoNotUseSHA1SpecificRule = CreateDiagnosticDescriptor(DoNotUseWeakCryptographicRuleId,
s_localizableDoNotUseSHA1Title,
s_localizableDoNotUseSHA1Description);
internal const string DoNotUseWeakCryptographyRuleId = "CA5350";
internal const string DoNotUseBrokenCryptographyRuleId = "CA5351";

internal const string CA5350HelpLink = "https://aka.ms/CA5350";
internal const string CA5351HelpLink = "https://aka.ms/CA5351";

private static readonly LocalizableString s_localizableDoNotUseWeakAlgorithmsTitle = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseWeakCryptographicAlgorithms),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseWeakAlgorithmsMessage = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseWeakCryptographicAlgorithmsMessage),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseWeakAlgorithmsDescription = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseWeakCryptographicAlgorithmsDescription),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseBrokenAlgorithmsTitle = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseBrokenCryptographicAlgorithms),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseBrokenAlgorithmsMessage = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseBrokenCryptographicAlgorithmsMessage),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));
private static readonly LocalizableString s_localizableDoNotUseBrokenAlgorithmsDescription = new LocalizableResourceString(
nameof(SystemSecurityCryptographyResources.DoNotUseBrokenCryptographicAlgorithmsDescription),
SystemSecurityCryptographyResources.ResourceManager,
typeof(SystemSecurityCryptographyResources));

internal static DiagnosticDescriptor DoNotUseBrokenCryptographyRule = CreateDiagnosticDescriptor(DoNotUseBrokenCryptographyRuleId,
s_localizableDoNotUseBrokenAlgorithmsTitle,
s_localizableDoNotUseBrokenAlgorithmsMessage,
s_localizableDoNotUseBrokenAlgorithmsDescription,
CA5351HelpLink);

internal static DiagnosticDescriptor DoNotUseWeakCryptographyRule = CreateDiagnosticDescriptor(DoNotUseWeakCryptographyRuleId,
s_localizableDoNotUseWeakAlgorithmsTitle,
s_localizableDoNotUseWeakAlgorithmsMessage,
s_localizableDoNotUseWeakAlgorithmsDescription,
CA5350HelpLink);

protected abstract SyntaxNodeAnalyzer GetAnalyzer(CompilationStartAnalysisContext context, CompilationSecurityTypes cryptTypes);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DoNotUseMD5SpecificRule, DoNotUseSHA1SpecificRule);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DoNotUseBrokenCryptographyRule, DoNotUseWeakCryptographyRule);

private static DiagnosticDescriptor CreateDiagnosticDescriptor(string ruleId, LocalizableString title, LocalizableString description, string uri = null)
private static DiagnosticDescriptor CreateDiagnosticDescriptor(string ruleId, LocalizableString title, LocalizableString message, LocalizableString description, string uri = null)
{
return new DiagnosticDescriptor(ruleId,
title,
title,
DiagnosticCategory.Security,
DiagnosticHelpers.DefaultDiagnosticSeverity,
isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
description: description,
helpLinkUri: uri,
customTags: WellKnownDiagnosticTags.Telemetry);
return new DiagnosticDescriptor(
ruleId,
title,
message,
DiagnosticCategory.Security,
DiagnosticHelpers.DefaultDiagnosticSeverity,
isEnabledByDefault: DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
description: description,
helpLinkUri: uri,
customTags: WellKnownDiagnosticTags.Telemetry);
}

public override void Initialize(AnalysisContext analysisContext)
Expand All @@ -66,7 +94,15 @@ private static bool ReferencesAnyTargetType(CompilationSecurityTypes types)
{
return types.MD5 != null
|| types.SHA1 != null
|| types.HMACSHA1 != null;
|| types.HMACSHA1 != null
|| types.DES != null
|| types.DSA != null
|| types.DSASignatureFormatter != null
|| types.HMACMD5 != null
|| types.RC2 != null
|| types.TripleDES != null
|| types.RIPEMD160 != null
|| types.HMACRIPEMD160 != null;
}

protected class SyntaxNodeAnalyzer
Expand All @@ -82,30 +118,100 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
SyntaxNode node = context.Node;
SemanticModel model = context.SemanticModel;

ISymbol symbol = node.GetDeclaredOrReferencedSymbol(model);
IMethodSymbol method = symbol as IMethodSymbol;

if (method == null)
{
return;
}

INamedTypeSymbol type = method.ContainingType;
DiagnosticDescriptor rule = null;
string[] messageArgs = new string[2];
string owningParentName = string.Empty;
SyntaxNode cur = node;

while (cur.Parent != null)
{
SyntaxNode pNode = cur.Parent;
ISymbol sym = pNode.GetDeclaredOrReferencedSymbol(model);

if (sym != null &&
!string.IsNullOrEmpty(sym.Name)
&& (
sym.Kind == SymbolKind.Method ||
sym.Kind == SymbolKind.NamedType
)
)
{
owningParentName = sym.Name;
break;
}

cur = pNode;
}

messageArgs[0] = owningParentName;

if (type.DerivesFrom(_cryptTypes.MD5))
{
rule = DoNotUseMD5SpecificRule;
rule = DoNotUseBrokenCryptographyRule;
messageArgs[1] = _cryptTypes.MD5.Name;
}
else if (type.DerivesFrom(_cryptTypes.SHA1))
{
rule = DoNotUseWeakCryptographyRule;
messageArgs[1] = _cryptTypes.SHA1.Name;
}
else if (type.DerivesFrom(_cryptTypes.HMACSHA1))
{
rule = DoNotUseWeakCryptographyRule;
messageArgs[1] = _cryptTypes.HMACSHA1.Name;
}
else if (type.DerivesFrom(_cryptTypes.DES))
{
rule = DoNotUseBrokenCryptographyRule;
messageArgs[1] = _cryptTypes.DES.Name;
}
else if ((method.ContainingType.DerivesFrom(_cryptTypes.DSA)
&& method.MetadataName == SecurityMemberNames.CreateSignature)
|| (type == _cryptTypes.DSASignatureFormatter
&& method.ContainingType.DerivesFrom(_cryptTypes.DSASignatureFormatter)
&& method.MetadataName == WellKnownMemberNames.InstanceConstructorName))
{
rule = DoNotUseBrokenCryptographyRule;
messageArgs[1] = _cryptTypes.DSA.Name;
}
else if (type.DerivesFrom(_cryptTypes.HMACMD5))
{
rule = DoNotUseBrokenCryptographyRule;
messageArgs[1] = _cryptTypes.HMACMD5.Name;
}
else if (type.DerivesFrom(_cryptTypes.RC2))
{
rule = DoNotUseBrokenCryptographyRule;
messageArgs[1] = _cryptTypes.RC2.Name;
}
else if (type.DerivesFrom(_cryptTypes.TripleDES))
{
rule = DoNotUseWeakCryptographyRule;
messageArgs[1] = _cryptTypes.TripleDES.Name;
}
else if (type.DerivesFrom(_cryptTypes.RIPEMD160))
{
rule = DoNotUseWeakCryptographyRule;
messageArgs[1] = _cryptTypes.RIPEMD160.Name;
}
else if (type.DerivesFrom(_cryptTypes.SHA1) ||
type.DerivesFrom(_cryptTypes.HMACSHA1))
else if (type.DerivesFrom(_cryptTypes.HMACRIPEMD160))
{
rule = DoNotUseSHA1SpecificRule;
rule = DoNotUseWeakCryptographyRule;
messageArgs[1] = _cryptTypes.HMACRIPEMD160.Name;
}

if (rule != null)
{
context.ReportDiagnostic(Diagnostic.Create(rule, node.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(rule, node.GetLocation(), messageArgs));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,33 @@ namespace Microsoft.NetCore.Analyzers.Security.Helpers
{
public class CompilationSecurityTypes
{
// Some of these types may only exist in .NET Framework and not in .NET Core, but that's okay, we'll look anyway.

public INamedTypeSymbol MD5 { get; private set; }
public INamedTypeSymbol SHA1 { get; private set; }
public INamedTypeSymbol HMACSHA1 { get; private set; }
public INamedTypeSymbol DES { get; private set; }
public INamedTypeSymbol DSA { get; private set; }
public INamedTypeSymbol DSASignatureFormatter { get; private set; }
public INamedTypeSymbol HMACMD5 { get; private set; }
public INamedTypeSymbol RC2 { get; private set; }
public INamedTypeSymbol TripleDES { get; private set; }
public INamedTypeSymbol RIPEMD160 { get; private set; }
public INamedTypeSymbol HMACRIPEMD160 { get; private set; }

public CompilationSecurityTypes(Compilation compilation)
{
MD5 = SecurityTypes.MD5(compilation);
SHA1 = SecurityTypes.SHA1(compilation);
HMACSHA1 = SecurityTypes.HMACSHA1(compilation);
DES = SecurityTypes.DES(compilation);
DSA = SecurityTypes.DSA(compilation);
DSASignatureFormatter = SecurityTypes.DSASignatureFormatter(compilation);
HMACMD5 = SecurityTypes.HMACMD5(compilation);
RC2 = SecurityTypes.RC2(compilation);
TripleDES = SecurityTypes.TripleDES(compilation);
RIPEMD160 = SecurityTypes.RIPEMD160(compilation);
HMACRIPEMD160 = SecurityTypes.HMACRIPEMD160(compilation);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

namespace Microsoft.NetCore.Analyzers.Security.Helpers
{
using System.Security.Cryptography;

internal static class SecurityMemberNames
{
// This is nameof(System.Security.Cryptography.DSA.CreateSignature), but DSA doesn't exist in .NET Standard 1.3.
public const string CreateSignature = nameof(CreateSignature);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,54 @@ public static INamedTypeSymbol MD5(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.MD5");
}

public static INamedTypeSymbol SHA1(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.SHA1");
}

public static INamedTypeSymbol HMACSHA1(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.HMACSHA1");
}
public static INamedTypeSymbol DES(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.DES");
}

public static INamedTypeSymbol DSA(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.DSA");
}

public static INamedTypeSymbol DSASignatureFormatter(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.DSASignatureFormatter");
}

public static INamedTypeSymbol HMACMD5(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.HMACMD5");
}

public static INamedTypeSymbol RC2(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.RC2");
}

public static INamedTypeSymbol TripleDES(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.TripleDES");
}

public static INamedTypeSymbol RIPEMD160(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.RIPEMD160");
}

public static INamedTypeSymbol HMACRIPEMD160(Compilation compilation)
{
return compilation.GetTypeByMetadataName("System.Security.Cryptography.HMACRIPEMD160");
}
}
}
Loading

0 comments on commit 100d223

Please sign in to comment.