use of java.nio.BufferUnderflowException in project platform_frameworks_base by android.
the class ApkSignatureSchemeV2Verifier method verifySigner.
private static X509Certificate[] verifySigner(ByteBuffer signerBlock, Map<Integer, byte[]> contentDigests, CertificateFactory certFactory) throws SecurityException, IOException {
ByteBuffer signedData = getLengthPrefixedSlice(signerBlock);
ByteBuffer signatures = getLengthPrefixedSlice(signerBlock);
byte[] publicKeyBytes = readLengthPrefixedByteArray(signerBlock);
int signatureCount = 0;
int bestSigAlgorithm = -1;
byte[] bestSigAlgorithmSignatureBytes = null;
List<Integer> signaturesSigAlgorithms = new ArrayList<>();
while (signatures.hasRemaining()) {
signatureCount++;
try {
ByteBuffer signature = getLengthPrefixedSlice(signatures);
if (signature.remaining() < 8) {
throw new SecurityException("Signature record too short");
}
int sigAlgorithm = signature.getInt();
signaturesSigAlgorithms.add(sigAlgorithm);
if (!isSupportedSignatureAlgorithm(sigAlgorithm)) {
continue;
}
if ((bestSigAlgorithm == -1) || (compareSignatureAlgorithm(sigAlgorithm, bestSigAlgorithm) > 0)) {
bestSigAlgorithm = sigAlgorithm;
bestSigAlgorithmSignatureBytes = readLengthPrefixedByteArray(signature);
}
} catch (IOException | BufferUnderflowException e) {
throw new SecurityException("Failed to parse signature record #" + signatureCount, e);
}
}
if (bestSigAlgorithm == -1) {
if (signatureCount == 0) {
throw new SecurityException("No signatures found");
} else {
throw new SecurityException("No supported signatures found");
}
}
String keyAlgorithm = getSignatureAlgorithmJcaKeyAlgorithm(bestSigAlgorithm);
Pair<String, ? extends AlgorithmParameterSpec> signatureAlgorithmParams = getSignatureAlgorithmJcaSignatureAlgorithm(bestSigAlgorithm);
String jcaSignatureAlgorithm = signatureAlgorithmParams.first;
AlgorithmParameterSpec jcaSignatureAlgorithmParams = signatureAlgorithmParams.second;
boolean sigVerified;
try {
PublicKey publicKey = KeyFactory.getInstance(keyAlgorithm).generatePublic(new X509EncodedKeySpec(publicKeyBytes));
Signature sig = Signature.getInstance(jcaSignatureAlgorithm);
sig.initVerify(publicKey);
if (jcaSignatureAlgorithmParams != null) {
sig.setParameter(jcaSignatureAlgorithmParams);
}
sig.update(signedData);
sigVerified = sig.verify(bestSigAlgorithmSignatureBytes);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | InvalidAlgorithmParameterException | SignatureException e) {
throw new SecurityException("Failed to verify " + jcaSignatureAlgorithm + " signature", e);
}
if (!sigVerified) {
throw new SecurityException(jcaSignatureAlgorithm + " signature did not verify");
}
// Signature over signedData has verified.
byte[] contentDigest = null;
signedData.clear();
ByteBuffer digests = getLengthPrefixedSlice(signedData);
List<Integer> digestsSigAlgorithms = new ArrayList<>();
int digestCount = 0;
while (digests.hasRemaining()) {
digestCount++;
try {
ByteBuffer digest = getLengthPrefixedSlice(digests);
if (digest.remaining() < 8) {
throw new IOException("Record too short");
}
int sigAlgorithm = digest.getInt();
digestsSigAlgorithms.add(sigAlgorithm);
if (sigAlgorithm == bestSigAlgorithm) {
contentDigest = readLengthPrefixedByteArray(digest);
}
} catch (IOException | BufferUnderflowException e) {
throw new IOException("Failed to parse digest record #" + digestCount, e);
}
}
if (!signaturesSigAlgorithms.equals(digestsSigAlgorithms)) {
throw new SecurityException("Signature algorithms don't match between digests and signatures records");
}
int digestAlgorithm = getSignatureAlgorithmContentDigestAlgorithm(bestSigAlgorithm);
byte[] previousSignerDigest = contentDigests.put(digestAlgorithm, contentDigest);
if ((previousSignerDigest != null) && (!MessageDigest.isEqual(previousSignerDigest, contentDigest))) {
throw new SecurityException(getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm) + " contents digest does not match the digest specified by a preceding signer");
}
ByteBuffer certificates = getLengthPrefixedSlice(signedData);
List<X509Certificate> certs = new ArrayList<>();
int certificateCount = 0;
while (certificates.hasRemaining()) {
certificateCount++;
byte[] encodedCert = readLengthPrefixedByteArray(certificates);
X509Certificate certificate;
try {
certificate = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(encodedCert));
} catch (CertificateException e) {
throw new SecurityException("Failed to decode certificate #" + certificateCount, e);
}
certificate = new VerbatimX509Certificate(certificate, encodedCert);
certs.add(certificate);
}
if (certs.isEmpty()) {
throw new SecurityException("No certificates listed");
}
X509Certificate mainCertificate = certs.get(0);
byte[] certificatePublicKeyBytes = mainCertificate.getPublicKey().getEncoded();
if (!Arrays.equals(publicKeyBytes, certificatePublicKeyBytes)) {
throw new SecurityException("Public key mismatch between certificate and signature record");
}
return certs.toArray(new X509Certificate[certs.size()]);
}
use of java.nio.BufferUnderflowException in project platform_frameworks_base by android.
the class DhcpPacket method decodeFullPacket.
/**
* Creates a concrete DhcpPacket from the supplied ByteBuffer. The
* buffer may have an L2 encapsulation (which is the full EthernetII
* format starting with the source-address MAC) or an L3 encapsulation
* (which starts with the IP header).
* <br>
* A subset of the optional parameters are parsed and are stored
* in object fields.
*/
@VisibleForTesting
static DhcpPacket decodeFullPacket(ByteBuffer packet, int pktType) throws ParseException {
// bootp parameters
int transactionId;
short secs;
Inet4Address clientIp;
Inet4Address yourIp;
Inet4Address nextIp;
Inet4Address relayIp;
byte[] clientMac;
List<Inet4Address> dnsServers = new ArrayList<>();
// aka router
List<Inet4Address> gateways = new ArrayList<>();
Inet4Address serverIdentifier = null;
Inet4Address netMask = null;
String message = null;
String vendorId = null;
String vendorInfo = null;
byte[] expectedParams = null;
String hostName = null;
String domainName = null;
Inet4Address ipSrc = null;
Inet4Address ipDst = null;
Inet4Address bcAddr = null;
Inet4Address requestedIp = null;
// The following are all unsigned integers. Internally we store them as signed integers of
// the same length because that way we're guaranteed that they can't be out of the range of
// the unsigned field in the packet. Callers wanting to pass in an unsigned value will need
// to cast it.
Short mtu = null;
Short maxMessageSize = null;
Integer leaseTime = null;
Integer T1 = null;
Integer T2 = null;
// dhcp options
byte dhcpType = (byte) 0xFF;
packet.order(ByteOrder.BIG_ENDIAN);
// check to see if we need to parse L2, IP, and UDP encaps
if (pktType == ENCAP_L2) {
if (packet.remaining() < MIN_PACKET_LENGTH_L2) {
throw new ParseException(DhcpErrorEvent.L2_TOO_SHORT, "L2 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L2);
}
byte[] l2dst = new byte[6];
byte[] l2src = new byte[6];
packet.get(l2dst);
packet.get(l2src);
short l2type = packet.getShort();
if (l2type != OsConstants.ETH_P_IP) {
throw new ParseException(DhcpErrorEvent.L2_WRONG_ETH_TYPE, "Unexpected L2 type 0x%04x, expected 0x%04x", l2type, OsConstants.ETH_P_IP);
}
}
if (pktType <= ENCAP_L3) {
if (packet.remaining() < MIN_PACKET_LENGTH_L3) {
throw new ParseException(DhcpErrorEvent.L3_TOO_SHORT, "L3 packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_L3);
}
byte ipTypeAndLength = packet.get();
int ipVersion = (ipTypeAndLength & 0xf0) >> 4;
if (ipVersion != 4) {
throw new ParseException(DhcpErrorEvent.L3_NOT_IPV4, "Invalid IP version %d", ipVersion);
}
// System.out.println("ipType is " + ipType);
byte ipDiffServicesField = packet.get();
short ipTotalLength = packet.getShort();
short ipIdentification = packet.getShort();
byte ipFlags = packet.get();
byte ipFragOffset = packet.get();
byte ipTTL = packet.get();
byte ipProto = packet.get();
short ipChksm = packet.getShort();
ipSrc = readIpAddress(packet);
ipDst = readIpAddress(packet);
if (ipProto != IP_TYPE_UDP) {
throw new ParseException(DhcpErrorEvent.L4_NOT_UDP, "Protocol not UDP: %d", ipProto);
}
// Skip options. This cannot cause us to read beyond the end of the buffer because the
// IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than
// MIN_PACKET_LENGTH_L3.
int optionWords = ((ipTypeAndLength & 0x0f) - 5);
for (int i = 0; i < optionWords; i++) {
packet.getInt();
}
// assume UDP
short udpSrcPort = packet.getShort();
short udpDstPort = packet.getShort();
short udpLen = packet.getShort();
short udpChkSum = packet.getShort();
// server-to-server packets, e.g. for relays.
if (!isPacketToOrFromClient(udpSrcPort, udpDstPort) && !isPacketServerToServer(udpSrcPort, udpDstPort)) {
// filter is set. http://b/26696823 .
throw new ParseException(DhcpErrorEvent.L4_WRONG_PORT, "Unexpected UDP ports %d->%d", udpSrcPort, udpDstPort);
}
}
// We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length.
if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) {
throw new ParseException(DhcpErrorEvent.BOOTP_TOO_SHORT, "Invalid type or BOOTP packet too short, %d < %d", packet.remaining(), MIN_PACKET_LENGTH_BOOTP);
}
byte type = packet.get();
byte hwType = packet.get();
int addrLen = packet.get() & 0xff;
byte hops = packet.get();
transactionId = packet.getInt();
secs = packet.getShort();
short bootpFlags = packet.getShort();
boolean broadcast = (bootpFlags & 0x8000) != 0;
byte[] ipv4addr = new byte[4];
try {
packet.get(ipv4addr);
clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
packet.get(ipv4addr);
relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr);
} catch (UnknownHostException ex) {
throw new ParseException(DhcpErrorEvent.L3_INVALID_IP, "Invalid IPv4 address: %s", Arrays.toString(ipv4addr));
}
// TODO: evaluate whether to make this test more liberal.
if (addrLen > HWADDR_LEN) {
addrLen = ETHER_BROADCAST.length;
}
clientMac = new byte[addrLen];
packet.get(clientMac);
// skip over address padding (16 octets allocated)
packet.position(packet.position() + (16 - addrLen) + // skip server host name (64 chars)
64 + // skip boot file name (128 chars)
128);
// Ensure this is a DHCP packet with a magic cookie, and not BOOTP. http://b/31850211
if (packet.remaining() < 4) {
throw new ParseException(DhcpErrorEvent.DHCP_NO_COOKIE, "not a DHCP message");
}
int dhcpMagicCookie = packet.getInt();
if (dhcpMagicCookie != DHCP_MAGIC_COOKIE) {
throw new ParseException(DhcpErrorEvent.DHCP_BAD_MAGIC_COOKIE, "Bad magic cookie 0x%08x, should be 0x%08x", dhcpMagicCookie, DHCP_MAGIC_COOKIE);
}
// parse options
boolean notFinishedOptions = true;
while ((packet.position() < packet.limit()) && notFinishedOptions) {
// cannot underflow because position < limit
final byte optionType = packet.get();
try {
if (optionType == DHCP_OPTION_END) {
notFinishedOptions = false;
} else if (optionType == DHCP_OPTION_PAD) {
// The pad option doesn't have a length field. Nothing to do.
} else {
int optionLen = packet.get() & 0xFF;
int expectedLen = 0;
switch(optionType) {
case DHCP_SUBNET_MASK:
netMask = readIpAddress(packet);
expectedLen = 4;
break;
case DHCP_ROUTER:
for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) {
gateways.add(readIpAddress(packet));
}
break;
case DHCP_DNS_SERVER:
for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) {
dnsServers.add(readIpAddress(packet));
}
break;
case DHCP_HOST_NAME:
expectedLen = optionLen;
hostName = readAsciiString(packet, optionLen, false);
break;
case DHCP_MTU:
expectedLen = 2;
mtu = packet.getShort();
break;
case DHCP_DOMAIN_NAME:
expectedLen = optionLen;
domainName = readAsciiString(packet, optionLen, false);
break;
case DHCP_BROADCAST_ADDRESS:
bcAddr = readIpAddress(packet);
expectedLen = 4;
break;
case DHCP_REQUESTED_IP:
requestedIp = readIpAddress(packet);
expectedLen = 4;
break;
case DHCP_LEASE_TIME:
leaseTime = Integer.valueOf(packet.getInt());
expectedLen = 4;
break;
case DHCP_MESSAGE_TYPE:
dhcpType = packet.get();
expectedLen = 1;
break;
case DHCP_SERVER_IDENTIFIER:
serverIdentifier = readIpAddress(packet);
expectedLen = 4;
break;
case DHCP_PARAMETER_LIST:
expectedParams = new byte[optionLen];
packet.get(expectedParams);
expectedLen = optionLen;
break;
case DHCP_MESSAGE:
expectedLen = optionLen;
message = readAsciiString(packet, optionLen, false);
break;
case DHCP_MAX_MESSAGE_SIZE:
expectedLen = 2;
maxMessageSize = Short.valueOf(packet.getShort());
break;
case DHCP_RENEWAL_TIME:
expectedLen = 4;
T1 = Integer.valueOf(packet.getInt());
break;
case DHCP_REBINDING_TIME:
expectedLen = 4;
T2 = Integer.valueOf(packet.getInt());
break;
case DHCP_VENDOR_CLASS_ID:
expectedLen = optionLen;
// Embedded nulls are safe as this does not get passed to netd.
vendorId = readAsciiString(packet, optionLen, true);
break;
case DHCP_CLIENT_IDENTIFIER:
{
// Client identifier
byte[] id = new byte[optionLen];
packet.get(id);
expectedLen = optionLen;
}
break;
case DHCP_VENDOR_INFO:
expectedLen = optionLen;
// Embedded nulls are safe as this does not get passed to netd.
vendorInfo = readAsciiString(packet, optionLen, true);
break;
default:
// ignore any other parameters
for (int i = 0; i < optionLen; i++) {
expectedLen++;
byte throwaway = packet.get();
}
}
if (expectedLen != optionLen) {
final int errorCode = DhcpErrorEvent.errorCodeWithOption(DhcpErrorEvent.DHCP_INVALID_OPTION_LENGTH, optionType);
throw new ParseException(errorCode, "Invalid length %d for option %d, expected %d", optionLen, optionType, expectedLen);
}
}
} catch (BufferUnderflowException e) {
final int errorCode = DhcpErrorEvent.errorCodeWithOption(DhcpErrorEvent.BUFFER_UNDERFLOW, optionType);
throw new ParseException(errorCode, "BufferUnderflowException");
}
}
DhcpPacket newPacket;
switch(dhcpType) {
case (byte) 0xFF:
throw new ParseException(DhcpErrorEvent.DHCP_NO_MSG_TYPE, "No DHCP message type option");
case DHCP_MESSAGE_TYPE_DISCOVER:
newPacket = new DhcpDiscoverPacket(transactionId, secs, clientMac, broadcast);
break;
case DHCP_MESSAGE_TYPE_OFFER:
newPacket = new DhcpOfferPacket(transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_REQUEST:
newPacket = new DhcpRequestPacket(transactionId, secs, clientIp, clientMac, broadcast);
break;
case DHCP_MESSAGE_TYPE_DECLINE:
newPacket = new DhcpDeclinePacket(transactionId, secs, clientIp, yourIp, nextIp, relayIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_ACK:
newPacket = new DhcpAckPacket(transactionId, secs, broadcast, ipSrc, clientIp, yourIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_NAK:
newPacket = new DhcpNakPacket(transactionId, secs, clientIp, yourIp, nextIp, relayIp, clientMac);
break;
case DHCP_MESSAGE_TYPE_INFORM:
newPacket = new DhcpInformPacket(transactionId, secs, clientIp, yourIp, nextIp, relayIp, clientMac);
break;
default:
throw new ParseException(DhcpErrorEvent.DHCP_UNKNOWN_MSG_TYPE, "Unimplemented DHCP type %d", dhcpType);
}
newPacket.mBroadcastAddress = bcAddr;
newPacket.mDnsServers = dnsServers;
newPacket.mDomainName = domainName;
newPacket.mGateways = gateways;
newPacket.mHostName = hostName;
newPacket.mLeaseTime = leaseTime;
newPacket.mMessage = message;
newPacket.mMtu = mtu;
newPacket.mRequestedIp = requestedIp;
newPacket.mRequestedParams = expectedParams;
newPacket.mServerIdentifier = serverIdentifier;
newPacket.mSubnetMask = netMask;
newPacket.mMaxMessageSize = maxMessageSize;
newPacket.mT1 = T1;
newPacket.mT2 = T2;
newPacket.mVendorId = vendorId;
newPacket.mVendorInfo = vendorInfo;
return newPacket;
}
use of java.nio.BufferUnderflowException in project cassandra by apache.
the class MapSerializer method deserializeForNativeProtocol.
public Map<K, V> deserializeForNativeProtocol(ByteBuffer bytes, ProtocolVersion version) {
try {
ByteBuffer input = bytes.duplicate();
int n = readCollectionSize(input, version);
if (n < 0)
throw new MarshalException("The data cannot be deserialized as a map");
// If the received bytes are not corresponding to a map, n might be a huge number.
// In such a case we do not want to initialize the map with that initialCapacity as it can result
// in an OOM when put is called (see CASSANDRA-12618). On the other hand we do not want to have to resize
// the map if we can avoid it, so we put a reasonable limit on the initialCapacity.
Map<K, V> m = new LinkedHashMap<K, V>(Math.min(n, 256));
for (int i = 0; i < n; i++) {
ByteBuffer kbb = readValue(input, version);
keys.validate(kbb);
ByteBuffer vbb = readValue(input, version);
values.validate(vbb);
m.put(keys.deserialize(kbb), values.deserialize(vbb));
}
if (input.hasRemaining())
throw new MarshalException("Unexpected extraneous bytes after map value");
return m;
} catch (BufferUnderflowException e) {
throw new MarshalException("Not enough bytes to read a map");
}
}
use of java.nio.BufferUnderflowException in project cassandra by apache.
the class ListSerializer method validateForNativeProtocol.
public void validateForNativeProtocol(ByteBuffer bytes, ProtocolVersion version) {
try {
ByteBuffer input = bytes.duplicate();
int n = readCollectionSize(input, version);
for (int i = 0; i < n; i++) elements.validate(readValue(input, version));
if (input.hasRemaining())
throw new MarshalException("Unexpected extraneous bytes after list value");
} catch (BufferUnderflowException e) {
throw new MarshalException("Not enough bytes to read a list");
}
}
use of java.nio.BufferUnderflowException in project cassandra by apache.
the class ListSerializer method deserializeForNativeProtocol.
public List<T> deserializeForNativeProtocol(ByteBuffer bytes, ProtocolVersion version) {
try {
ByteBuffer input = bytes.duplicate();
int n = readCollectionSize(input, version);
if (n < 0)
throw new MarshalException("The data cannot be deserialized as a list");
// If the received bytes are not corresponding to a list, n might be a huge number.
// In such a case we do not want to initialize the list with that size as it can result
// in an OOM (see CASSANDRA-12618). On the other hand we do not want to have to resize the list
// if we can avoid it, so we put a reasonable limit on the initialCapacity.
List<T> l = new ArrayList<T>(Math.min(n, 256));
for (int i = 0; i < n; i++) {
// We can have nulls in lists that are used for IN values
ByteBuffer databb = readValue(input, version);
if (databb != null) {
elements.validate(databb);
l.add(elements.deserialize(databb));
} else {
l.add(null);
}
}
if (input.hasRemaining())
throw new MarshalException("Unexpected extraneous bytes after list value");
return l;
} catch (BufferUnderflowException e) {
throw new MarshalException("Not enough bytes to read a list");
}
}
Aggregations