blob: a68151d0ae05bc8141c1108a24d32b616dddf16c [file] [log] [blame]
// Copyright 2017 Google Inc.
//
// 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.google.crypto.tink.signature.internal;
import com.google.crypto.tink.proto.EcdsaParams;
import com.google.crypto.tink.proto.EcdsaSignatureEncoding;
import com.google.crypto.tink.proto.EllipticCurveType;
import com.google.crypto.tink.proto.HashType;
import com.google.crypto.tink.proto.RsaSsaPkcs1Params;
import com.google.crypto.tink.proto.RsaSsaPssParams;
import com.google.crypto.tink.subtle.EllipticCurves;
import com.google.crypto.tink.subtle.Enums;
import java.security.GeneralSecurityException;
/** Utility functions to convert to and from signature-related proto. */
public final class SigUtil {
static final String INVALID_PARAMS = "Invalid ECDSA parameters";
/**
* Validates Ecdsa's parameters. The hash's strength must not be weaker than the curve's strength.
*
* @param params the Ecdsa's parameters protocol buffer.
* @throws GeneralSecurityException iff it's invalid.
*/
public static void validateEcdsaParams(EcdsaParams params) throws GeneralSecurityException {
EcdsaSignatureEncoding encoding = params.getEncoding();
HashType hash = params.getHashType();
EllipticCurveType curve = params.getCurve();
switch (encoding) {
case DER: // fall through
case IEEE_P1363:
break;
default:
throw new GeneralSecurityException("unsupported signature encoding");
}
switch (curve) {
case NIST_P256:
// Using SHA512 for curve P256 is fine. However, only the 256 leftmost bits of the hash is
// used in signature computation. Therefore, we don't allow it here to prevent security
// illusion.
if (hash != HashType.SHA256) {
throw new GeneralSecurityException(INVALID_PARAMS);
}
break;
case NIST_P384:
if (hash != HashType.SHA384 && hash != HashType.SHA512) {
throw new GeneralSecurityException(INVALID_PARAMS);
}
break;
case NIST_P521:
if (hash != HashType.SHA512) {
throw new GeneralSecurityException(INVALID_PARAMS);
}
break;
default:
throw new GeneralSecurityException(INVALID_PARAMS);
}
}
/**
* Validates RsaSsaPkcs1's parameters. As SHA1 is unsafe, we will only support SHA256 and SHA512
* for digital signature.
*
* @param params the RsaSsaPkcs1Params protocol buffer.
* @throws GeneralSecurityException iff it's invalid.
*/
public static void validateRsaSsaPkcs1Params(RsaSsaPkcs1Params params)
throws GeneralSecurityException {
toHashType(params.getHashType());
}
/**
* Validates RsaSsaPss's parameters.
*
* <ul>
* <li>The MGF1 hash function must be the same as the signature hash function.
* <li>The hash function used must be either SHA256, SHA384, or SHA512.
* <li>The salt length must be non-zero.
* <ul>
*
* @param params the RsaSsaPssParams protocol buffer.
* @throws GeneralSecurityException iff it's invalid.
*/
public static void validateRsaSsaPssParams(RsaSsaPssParams params)
throws GeneralSecurityException {
toHashType(params.getSigHash());
if (params.getSigHash() != params.getMgf1Hash()) {
throw new GeneralSecurityException("MGF1 hash is different from signature hash");
}
if (params.getSaltLength() < 0) {
throw new GeneralSecurityException("salt length is negative");
}
}
/**
* Converts protobuf enum {@code HashType} to raw Java enum {@code Enums.HashType}.
*
* @throws GeneralSecurityException if the HashType is not SHA256, SHA384, or SHA512.
*/
public static Enums.HashType toHashType(HashType hash) throws GeneralSecurityException {
switch (hash) {
case SHA256:
return Enums.HashType.SHA256;
case SHA384:
return Enums.HashType.SHA384;
case SHA512:
return Enums.HashType.SHA512;
default:
break;
}
throw new GeneralSecurityException("unsupported hash type: " + hash.name());
}
/** Converts protobuf enum {@code EllipticCurveType} to raw Java enum {code CurveType}. */
public static EllipticCurves.CurveType toCurveType(EllipticCurveType type)
throws GeneralSecurityException {
switch (type) {
case NIST_P256:
return EllipticCurves.CurveType.NIST_P256;
case NIST_P384:
return EllipticCurves.CurveType.NIST_P384;
case NIST_P521:
return EllipticCurves.CurveType.NIST_P521;
default:
throw new GeneralSecurityException("unknown curve type: " + type.name());
}
}
/**
* Converts protobuf enum {@code EcdsaSignatureEncoding} to raw Java enum {code
* EllipticCurves.EcdsaEncoding}.
*/
public static EllipticCurves.EcdsaEncoding toEcdsaEncoding(EcdsaSignatureEncoding encoding)
throws GeneralSecurityException {
switch (encoding) {
case IEEE_P1363:
return EllipticCurves.EcdsaEncoding.IEEE_P1363;
case DER:
return EllipticCurves.EcdsaEncoding.DER;
default:
throw new GeneralSecurityException("unknown ECDSA encoding: " + encoding.name());
}
}
private SigUtil() {}
}