aboutsummaryrefslogtreecommitdiffstats
path: root/lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java
diff options
context:
space:
mode:
Diffstat (limited to 'lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java')
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java161
1 files changed, 0 insertions, 161 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java
deleted file mode 100644
index 4900fea..0000000
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/SecureRandomDetector.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.lint.checks;
-
-import com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.tools.lint.detector.api.Category;
-import com.android.tools.lint.detector.api.ClassContext;
-import com.android.tools.lint.detector.api.Detector;
-import com.android.tools.lint.detector.api.Detector.ClassScanner;
-import com.android.tools.lint.detector.api.Issue;
-import com.android.tools.lint.detector.api.LintUtils;
-import com.android.tools.lint.detector.api.Scope;
-import com.android.tools.lint.detector.api.Severity;
-
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.tree.AbstractInsnNode;
-import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.InsnList;
-import org.objectweb.asm.tree.MethodInsnNode;
-import org.objectweb.asm.tree.MethodNode;
-import org.objectweb.asm.tree.analysis.Analyzer;
-import org.objectweb.asm.tree.analysis.AnalyzerException;
-import org.objectweb.asm.tree.analysis.BasicInterpreter;
-import org.objectweb.asm.tree.analysis.BasicValue;
-import org.objectweb.asm.tree.analysis.Frame;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Checks for hardcoded seeds with random numbers.
- */
-public class SecureRandomDetector extends Detector implements ClassScanner {
- /** Unregistered activities and services */
- public static final Issue ISSUE = Issue.create(
- "SecureRandom", //$NON-NLS-1$
- "Looks for suspicious usage of the SecureRandom class",
-
- "Specifying a fixed seed will cause the instance to return a predictable sequence " +
- "of numbers. This may be useful for testing but it is not appropriate for secure use.",
-
- Category.PERFORMANCE,
- 9,
- Severity.WARNING,
- SecureRandomDetector.class,
- Scope.CLASS_FILE_SCOPE).
- setMoreInfo("http://developer.android.com/reference/java/security/SecureRandom.html");
-
- private static final String SET_SEED = "setSeed"; //$NON-NLS-1$
- private static final String OWNER_SECURE_RANDOM = "java/security/SecureRandom"; //$NON-NLS-1$
- private static final String OWNER_RANDOM = "java/util/Random"; //$NON-NLS-1$
- private static final String VM_SECURE_RANDOM = 'L' + OWNER_SECURE_RANDOM + ';';
- /** Method description for a method that takes a long argument (no return type specified */
- private static final String LONG_ARG = "(J)"; //$NON-NLS-1$
-
- /** Constructs a new {@link SecureRandomDetector} */
- public SecureRandomDetector() {
- }
-
- // ---- Implements ClassScanner ----
-
- @Override
- @Nullable
- public List<String> getApplicableCallNames() {
- return Collections.singletonList(SET_SEED);
- }
-
- @Override
- public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode,
- @NonNull MethodNode method, @NonNull MethodInsnNode call) {
- String owner = call.owner;
- String desc = call.desc;
- if (owner.equals(OWNER_SECURE_RANDOM)) {
- if (desc.startsWith(LONG_ARG)) {
- checkValidSetSeed(context, call);
- } else if (desc.startsWith("([B)")) { //$NON-NLS-1$
- // setSeed(byte[]) ...
- // We could do some flow analysis here to see whether the byte array getting
- // passed in appears to be fixed.
- // However, people calling this constructor rather than the simpler one
- // with a fixed integer are probably less likely to make that mistake... right?
- }
- } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) {
- // Called setSeed(long) on an instanceof a Random object. Flag this if the instance
- // is likely a SecureRandom.
-
- // Track allocations such that we know whether the type of the call
- // is on a SecureRandom rather than a Random
- Analyzer analyzer = new Analyzer(new BasicInterpreter() {
- @Override
- public BasicValue newValue(Type type) {
- if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) {
- return new BasicValue(type);
- }
- return super.newValue(type);
- }
- });
- try {
- Frame[] frames = analyzer.analyze(classNode.name, method);
- InsnList instructions = method.instructions;
- Frame frame = frames[instructions.indexOf(call)];
- int stackSlot = frame.getStackSize();
- for (Type type : Type.getArgumentTypes(desc)) {
- stackSlot -= type.getSize();
- }
- BasicValue stackValue = (BasicValue) frame.getStack(stackSlot);
- Type type = stackValue.getType();
- if (type != null && type.getDescriptor().equals(VM_SECURE_RANDOM)) {
- checkValidSetSeed(context, call);
- }
- } catch (AnalyzerException e) {
- context.log(e, null);
- }
- } else if (owner.equals(OWNER_RANDOM) && desc.startsWith(LONG_ARG)) {
- // Called setSeed(long) on an instanceof a Random object. Flag this if the instance
- // is likely a SecureRandom.
- // TODO
- }
- }
-
- private void checkValidSetSeed(ClassContext context, MethodInsnNode call) {
- assert call.name.equals(SET_SEED);
-
- // Make sure the argument passed is not a literal
- AbstractInsnNode prev = LintUtils.getPrevInstruction(call);
- if (prev == null) {
- return;
- }
- int opcode = prev.getOpcode();
- if (opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 || opcode == Opcodes.LDC) {
- context.report(ISSUE, context.getLocation(call),
- "Do not call setSeed() on a SecureRandom with a fixed seed: " +
- "it is not secure. Use getSeed().",
- null);
- } else if (opcode == Opcodes.INVOKESTATIC) {
- String methodName = ((MethodInsnNode) prev).name;
- if (methodName.equals("currentTimeMillis") || methodName.equals("nanoTime")) {
- context.report(ISSUE, context.getLocation(call),
- "It is dangerous to seed SecureRandom with the current time because " +
- "that value is more predictable to an attacker than the default seed.",
- null);
- }
- }
- }
-}