1 /* 2 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.IOException; 29 import java.util.ArrayList; 30 import java.util.Collection; 31 32 import javax.net.ssl.SSLProtocolException; 33 34 /* 35 * [RFC5246] The client uses the "signature_algorithms" extension to 36 * indicate to the server which signature/hash algorithm pairs may be 37 * used in digital signatures. The "extension_data" field of this 38 * extension contains a "supported_signature_algorithms" value. 39 * 40 * enum { 41 * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), 42 * sha512(6), (255) 43 * } HashAlgorithm; 44 * 45 * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } 46 * SignatureAlgorithm; 47 * 48 * struct { 49 * HashAlgorithm hash; 50 * SignatureAlgorithm signature; 51 * } SignatureAndHashAlgorithm; 52 * 53 * SignatureAndHashAlgorithm 54 * supported_signature_algorithms<2..2^16-2>; 55 */ 56 final class SignatureAlgorithmsExtension extends HelloExtension { 57 58 private Collection<SignatureAndHashAlgorithm> algorithms; 59 private int algorithmsLen; // length of supported_signature_algorithms 60 61 SignatureAlgorithmsExtension( 62 Collection<SignatureAndHashAlgorithm> signAlgs) { 63 64 super(ExtensionType.EXT_SIGNATURE_ALGORITHMS); 65 66 algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs); 67 algorithmsLen = 68 SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size(); 69 } 70 71 SignatureAlgorithmsExtension(HandshakeInStream s, int len) 72 throws IOException { 73 super(ExtensionType.EXT_SIGNATURE_ALGORITHMS); 74 75 algorithmsLen = s.getInt16(); 76 if (algorithmsLen == 0 || algorithmsLen + 2 != len) { 77 throw new SSLProtocolException("Invalid " + type + " extension"); 78 } 79 80 algorithms = new ArrayList<SignatureAndHashAlgorithm>(); 81 int remains = algorithmsLen; 82 int sequence = 0; 83 while (remains > 1) { // needs at least two bytes 84 int hash = s.getInt8(); // hash algorithm 85 int signature = s.getInt8(); // signature algorithm 86 87 SignatureAndHashAlgorithm algorithm = 88 SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence); 89 algorithms.add(algorithm); 90 remains -= 2; // one byte for hash, one byte for signature 91 } 92 93 if (remains != 0) { 94 throw new SSLProtocolException("Invalid server_name extension"); 95 } 96 } 97 98 Collection<SignatureAndHashAlgorithm> getSignAlgorithms() { 99 return algorithms; 100 } 101 102 @Override 103 int length() { 104 return 6 + algorithmsLen; 105 } 106 107 @Override 108 void send(HandshakeOutStream s) throws IOException { 109 s.putInt16(type.id); 110 s.putInt16(algorithmsLen + 2); 111 s.putInt16(algorithmsLen); 112 113 for (SignatureAndHashAlgorithm algorithm : algorithms) { 114 s.putInt8(algorithm.getHashValue()); // HashAlgorithm 115 s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm 116 } 117 } 118 119 @Override 120 public String toString() { 121 StringBuilder sb = new StringBuilder(); 122 sb.append("Extension ").append(type).append(", signature_algorithms: "); 123 boolean opened = false; 124 for (SignatureAndHashAlgorithm signAlg : algorithms) { 125 if (opened) { 126 sb.append(", ").append(signAlg.getAlgorithmName()); 127 } else { 128 sb.append(signAlg.getAlgorithmName()); 129 opened = true; 130 } 131 } 132 return sb.toString(); 133 } 134 } 135