/
DtlsTestTools.java
152 lines (131 loc) · 6.18 KB
/
DtlsTestTools.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*******************************************************************************
* Copyright (c) 2015, 2016 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v20.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Kai Hudalla (Bosch Software Innovations GmbH) - initial creation
* Kai Hudalla (Bosch Software Innovations GmbH) - add method for retrieving
* trust anchor
* Kai Hudalla (Bosch Software Innovations GmbH) - explicitly support retrieving client & server keys
* and certificate chains
******************************************************************************/
package org.eclipse.californium.scandium.dtls;
import static org.junit.Assert.assertFalse;
import java.net.InetSocketAddress;
import java.util.List;
import org.eclipse.californium.elements.util.ClockUtil;
import org.eclipse.californium.elements.util.DatagramReader;
import org.eclipse.californium.elements.util.DatagramWriter;
import org.eclipse.californium.elements.util.TestCertificatesTools;
import org.eclipse.californium.scandium.util.ServerName;
public final class DtlsTestTools extends TestCertificatesTools {
public static final long MAX_SEQUENCE_NO = 281474976710655L; // 2^48 - 1
private DtlsTestTools() {
}
public static Record getRecordForMessage(int epoch, int seqNo, DTLSMessage msg, InetSocketAddress peer) {
byte[] dtlsRecord = newDTLSRecord(msg.getContentType().getCode(), epoch, seqNo, msg.toByteArray());
List<Record> list = DtlsTestTools.fromByteArray(dtlsRecord, peer, null, ClockUtil.nanoRealtime());
assertFalse("Should be able to deserialize DTLS Record from byte array", list.isEmpty());
return list.get(0);
}
public static final byte[] newDTLSRecord(int typeCode, int epoch, long sequenceNo, byte[] fragment) {
ProtocolVersion protocolVer = ProtocolVersion.VERSION_DTLS_1_2;
// the record header contains a type code, version, epoch, sequenceNo, length
DatagramWriter writer = new DatagramWriter();
writer.write(typeCode, 8);
writer.write(protocolVer.getMajor(), 8);
writer.write(protocolVer.getMinor(), 8);
writer.write(epoch, 16);
writer.writeLong(sequenceNo, 48);
writer.write(fragment.length, 16);
writer.writeBytes(fragment);
return writer.toByteArray();
}
public static byte[] newClientCertificateTypesExtension(int... types) {
DatagramWriter writer = new DatagramWriter();
writer.write(types.length, 8);
for (int type : types) {
writer.write(type, 8);
}
return newHelloExtension(19, writer.toByteArray());
}
public static byte[] newServerCertificateTypesExtension(int... types) {
DatagramWriter writer = new DatagramWriter();
writer.write(types.length, 8);
for (int type : types) {
writer.write(type, 8);
}
return newHelloExtension(20, writer.toByteArray());
}
public static byte[] newSupportedEllipticCurvesExtension(int... curveIds) {
DatagramWriter writer = new DatagramWriter();
writer.write(curveIds.length * 2, 16);
for (int type : curveIds) {
writer.write(type, 16);
}
return newHelloExtension(10, writer.toByteArray());
}
public static byte[] newMaxFragmentLengthExtension(int lengthCode) {
return newHelloExtension(1, new byte[] { (byte) lengthCode });
}
public static byte[] newServerNameExtension(final String hostName) {
byte[] name = hostName.getBytes(ServerName.CHARSET);
DatagramWriter writer = new DatagramWriter();
writer.write(name.length + 3, 16); // server_name_list_length
writer.writeByte((byte) 0x00);
writer.write(name.length, 16);
writer.writeBytes(name);
return newHelloExtension(0, writer.toByteArray());
}
public static byte[] newHelloExtension(int typeCode, byte[] extensionBytes) {
DatagramWriter writer = new DatagramWriter();
writer.write(typeCode, 16);
writer.write(extensionBytes.length, 16);
writer.writeBytes(extensionBytes);
return writer.toByteArray();
}
public static <T extends HandshakeMessage> T fromByteArray(byte[] byteArray, HandshakeParameter parameter, InetSocketAddress peerAddress) throws HandshakeException {
HandshakeMessage hmsg = HandshakeMessage.fromByteArray(byteArray, peerAddress);
return fromHandshakeMessage(hmsg, parameter);
}
@SuppressWarnings("unchecked")
public static <T extends HandshakeMessage> T fromHandshakeMessage(HandshakeMessage message,
HandshakeParameter parameter) throws HandshakeException {
if (message instanceof GenericHandshakeMessage) {
return (T) HandshakeMessage.fromGenericHandshakeMessage((GenericHandshakeMessage) message, parameter);
} else {
return (T) message;
}
}
/**
* Parses a sequence of <em>DTLSCiphertext</em> structures into {@code Record} instances.
*
* The binary representation is expected to comply with the <em>DTLSCiphertext</em> structure
* defined in <a href="http://tools.ietf.org/html/rfc6347#section-4.3.1">RFC6347, Section 4.3.1</a>.
*
* @param byteArray the raw binary representation containing one or more DTLSCiphertext structures
* @param peerAddress the IP address and port of the peer from which the bytes have been
* received
* @param cidGenerator the connection id generator. May be {@code null}.
* @param receiveNanos uptime nanoseconds of receiving this record
* @return the {@code Record} instances
* @throws NullPointerException if either one of the byte array or peer address is {@code null}
*/
public static List<Record> fromByteArray(byte[] byteArray, InetSocketAddress peerAddress, ConnectionIdGenerator cidGenerator, long receiveNanos) {
if (byteArray == null) {
throw new NullPointerException("Byte array must not be null");
} else if (peerAddress == null) {
throw new NullPointerException("Peer address must not be null");
}
DatagramReader reader = new DatagramReader(byteArray, false);
return Record.fromReader(reader, peerAddress, cidGenerator, receiveNanos);
}
}