1 /* 2 * Copyright(C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.javacard.keymaster; 18 19 import javacard.framework.ISO7816; 20 import javacard.framework.ISOException; 21 22 /** 23 * This class constructs the Cose messages like CoseKey, CoseMac0, MacStructure, CoseSign1, 24 * SignStructure, CoseEncrypt, EncryptStructure and ReceipientStructures. 25 */ 26 public class KMCose { 27 28 // COSE SIGN1 29 public static final byte COSE_SIGN1_ENTRY_COUNT = 4; 30 public static final byte COSE_SIGN1_PROTECTED_PARAMS_OFFSET = 0; 31 public static final byte COSE_SIGN1_PAYLOAD_OFFSET = 2; 32 public static final byte COSE_SIGN1_SIGNATURE_OFFSET = 3; 33 // COSE MAC0 34 public static final byte COSE_MAC0_ENTRY_COUNT = 4; 35 public static final byte COSE_MAC0_PROTECTED_PARAMS_OFFSET = 0; 36 public static final byte COSE_MAC0_PAYLOAD_OFFSET = 2; 37 public static final byte COSE_MAC0_TAG_OFFSET = 3; 38 // COSE ENCRYPT 39 public static final byte COSE_ENCRYPT_ENTRY_COUNT = 4; 40 public static final byte COSE_ENCRYPT_STRUCTURE_ENTRY_COUNT = 3; 41 public static final byte COSE_ENCRYPT_RECIPIENT_ENTRY_COUNT = 3; 42 43 // COSE Labels 44 public static final byte COSE_LABEL_ALGORITHM = 1; 45 public static final byte COSE_LABEL_KEYID = 4; 46 public static final byte COSE_LABEL_IV = 5; 47 public static final byte COSE_LABEL_COSE_KEY = (byte) 0xFF; // -1 48 49 // COSE Algorithms 50 public static final byte COSE_ALG_AES_GCM_256 = 3; // AES-GCM mode w/ 256-bit key, 128-bit tag. 51 public static final byte COSE_ALG_HMAC_256 = 5; // HMAC w/ SHA-256 52 public static final byte COSE_ALG_ES256 = (byte) 0xF9; // ECDSA w/ SHA-256; -7 53 public static final byte COSE_ALG_ECDH_ES_HKDF_256 = (byte) 0xE7; // ECDH-EC+HKDF-256; -25 54 55 // COSE P256 EC Curve 56 public static final byte COSE_ECCURVE_256 = 1; 57 58 // COSE key types 59 public static final byte COSE_KEY_TYPE_EC2 = 2; 60 public static final byte COSE_KEY_TYPE_SYMMETRIC_KEY = 4; 61 62 // COSE Key Operations 63 public static final byte COSE_KEY_OP_SIGN = 1; 64 public static final byte COSE_KEY_OP_VERIFY = 2; 65 public static final byte COSE_KEY_OP_ENCRYPT = 3; 66 public static final byte COSE_KEY_OP_DECRYPT = 4; 67 68 // AES GCM 69 public static final short AES_GCM_KEY_SIZE_BITS = 256; 70 // Cose key parameters. 71 public static final short COSE_KEY_KEY_TYPE = 1; 72 public static final short COSE_KEY_KEY_ID = 2; 73 public static final short COSE_KEY_ALGORITHM = 3; 74 public static final short COSE_KEY_CURVE = -1; 75 public static final short COSE_KEY_PUBKEY_X = -2; 76 public static final short COSE_KEY_PUBKEY_Y = -3; 77 public static final short COSE_KEY_PRIV_KEY = -4; 78 public static final byte[] COSE_TEST_KEY = { 79 (byte) 0xFF, (byte) 0xFE, (byte) 0xEE, (byte) 0x90 80 }; // -70000 81 public static final byte COSE_KEY_MAX_SIZE = 4; 82 83 // kdfcontext strings 84 public static final byte[] client = {0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74}; 85 public static final byte[] server = {0x73, 0x65, 0x72, 0x76, 0x65, 0x72}; 86 // Context strings 87 public static final byte[] MAC_CONTEXT = {0x4d, 0x41, 0x43, 0x30}; // MAC0 88 public static final byte[] SIGNATURE1_CONTEXT = { 89 0x53, 0x69, 0x67, 0x6E, 0x61, 0x74, 0x75, 0x72, 0x65, 0x31 90 }; // Signature1 91 public static final byte[] ENCRYPT_CONTEXT = { 92 0x45, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74 93 }; // Encrypt 94 // Certificate payload supported keys 95 public static final byte ISSUER = (byte) 0x01; 96 public static final byte SUBJECT = (byte) 0x02; 97 public static final byte[] SUBJECT_PUBLIC_KEY = { 98 (byte) 0xFF, (byte) 0xB8, (byte) 0xBB, (byte) 0xA8 99 }; 100 public static final byte[] KEY_USAGE = {(byte) 0xFF, (byte) 0xB8, (byte) 0xBB, (byte) 0xA7}; 101 // text strings 102 public static final byte[] TEST_ISSUER_NAME = { 103 (byte) 0x49, 0x73, 0x73, 0x75, 0x65, 0x72 104 }; // "Issuer" 105 public static final byte[] TEST_SUBJECT_NAME = { 106 0x53, 0x75, 0x62, 0x6A, 0x65, 0x63, 0x74 107 }; // "Subject" 108 public static final byte[] KEY_USAGE_SIGN = {0x20}; // Key usage sign 109 110 public static final short[] COSE_KEY_LABELS = { 111 KMCose.COSE_KEY_KEY_TYPE, 112 KMCose.COSE_KEY_KEY_ID, 113 KMCose.COSE_KEY_ALGORITHM, 114 KMCose.COSE_KEY_CURVE, 115 KMCose.COSE_KEY_PUBKEY_X, 116 KMCose.COSE_KEY_PUBKEY_Y, 117 KMCose.COSE_KEY_PRIV_KEY 118 }; 119 public static final short[] COSE_HEADER_LABELS = { 120 KMCose.COSE_LABEL_ALGORITHM, 121 KMCose.COSE_LABEL_KEYID, 122 KMCose.COSE_LABEL_IV, 123 KMCose.COSE_LABEL_COSE_KEY 124 }; 125 126 /** 127 * Constructs the Cose MAC structure. 128 * 129 * @param protectedHeader Bstr pointer which holds the protected header. 130 * @param extAad Bstr pointer which holds the external Aad. 131 * @param payload Bstr pointer which holds the payload of the MAC structure. 132 * @return KMArray instance of MAC structure. 133 */ constructCoseMacStructure( short protectedHeader, short extAad, short payload)134 public static short constructCoseMacStructure( 135 short protectedHeader, short extAad, short payload) { 136 // Create MAC Structure and compute HMAC as per https://tools.ietf.org/html/rfc8152#section-6.3 137 // MAC_structure = [ 138 // context : "MAC" / "MAC0", 139 // protected : empty_or_serialized_map, 140 // external_aad : bstr, 141 // payload : bstr 142 // ] 143 short arrPtr = KMArray.instance(KMCose.COSE_MAC0_ENTRY_COUNT); 144 // 1 - Context 145 KMArray.cast(arrPtr) 146 .add( 147 (short) 0, 148 KMTextString.instance( 149 KMCose.MAC_CONTEXT, (short) 0, (short) KMCose.MAC_CONTEXT.length)); 150 // 2 - Protected headers. 151 KMArray.cast(arrPtr).add((short) 1, protectedHeader); 152 // 3 - external aad 153 KMArray.cast(arrPtr).add((short) 2, extAad); 154 // 4 - payload. 155 KMArray.cast(arrPtr).add((short) 3, payload); 156 return arrPtr; 157 } 158 159 /** 160 * Constructs the COSE_MAC0 object. 161 * 162 * @param protectedHeader Bstr pointer which holds the protected header. 163 * @param unprotectedHeader Bstr pointer which holds the unprotected header. 164 * @param payload Bstr pointer which holds the payload of the MAC structure. 165 * @param tag Bstr pointer which holds the tag value. 166 * @return KMArray instance of COSE_MAC0 object. 167 */ constructCoseMac0( short protectedHeader, short unprotectedHeader, short payload, short tag)168 public static short constructCoseMac0( 169 short protectedHeader, short unprotectedHeader, short payload, short tag) { 170 // Construct Cose_MAC0 171 // COSE_Mac0 = [ 172 // protectedHeader, 173 // unprotectedHeader, 174 // payload : bstr / nil, 175 // tag : bstr, 176 // ] 177 short arrPtr = KMArray.instance(KMCose.COSE_MAC0_ENTRY_COUNT); 178 // 1 - protected headers 179 KMArray.cast(arrPtr).add((short) 0, protectedHeader); 180 // 2 - unprotected headers 181 KMArray.cast(arrPtr).add((short) 1, unprotectedHeader); 182 // 2 - payload 183 KMArray.cast(arrPtr).add((short) 2, payload); 184 // 3 - tag 185 KMArray.cast(arrPtr).add((short) 3, tag); 186 // Do encode. 187 return arrPtr; 188 } 189 190 /** 191 * Constructs the COSE_Signature structure. 192 * 193 * @param protectedHeader Bstr pointer which holds the protected header. 194 * @param extAad Bstr pointer which holds the aad. 195 * @param payload Bstr pointer which holds the payload. 196 * @return KMArray instance of COSE_Signature object. 197 */ constructCoseSignStructure( short protectedHeader, short extAad, short payload)198 public static short constructCoseSignStructure( 199 short protectedHeader, short extAad, short payload) { 200 // Sig_structure = [ 201 // context : "Signature" / "Signature1" / "CounterSignature", 202 // body_protected : empty_or_serialized_map, 203 // ? sign_protected : empty_or_serialized_map, 204 // external_aad : bstr, 205 // payload : bstr 206 // ] 207 short arrPtr = KMArray.instance(KMCose.COSE_SIGN1_ENTRY_COUNT); 208 // 1 - Context 209 KMArray.cast(arrPtr) 210 .add( 211 (short) 0, 212 KMTextString.instance( 213 KMCose.SIGNATURE1_CONTEXT, (short) 0, (short) KMCose.SIGNATURE1_CONTEXT.length)); 214 // 2 - Protected headers. 215 KMArray.cast(arrPtr).add((short) 1, protectedHeader); 216 // 3 - external aad 217 KMArray.cast(arrPtr).add((short) 2, extAad); 218 // 4 - payload. 219 KMArray.cast(arrPtr).add((short) 3, payload); 220 return arrPtr; 221 } 222 223 /** 224 * Constructs the COSE_Sign1 object. 225 * 226 * @param protectedHeader Bstr pointer which holds the protected header. 227 * @param unProtectedHeader Bstr pointer which holds the unprotected header. 228 * @param payload Bstr pointer which holds the payload. 229 * @param signature Bstr pointer which holds the signature. 230 * @return KMArray instance of COSE_Sign1 object. 231 */ constructCoseSign1( short protectedHeader, short unProtectedHeader, short payload, short signature)232 public static short constructCoseSign1( 233 short protectedHeader, short unProtectedHeader, short payload, short signature) { 234 // COSE_Sign = [ 235 // protectedHeader, 236 // unprotectedHeader, 237 // payload : bstr / nil, 238 // signatures : [+ COSE_Signature] 239 // ] 240 short arrPtr = KMArray.instance(KMCose.COSE_SIGN1_ENTRY_COUNT); 241 // 1 - protected headers 242 KMArray.cast(arrPtr).add((short) 0, protectedHeader); 243 // 2 - unprotected headers 244 KMArray.cast(arrPtr).add((short) 1, unProtectedHeader); 245 // 2 - payload 246 KMArray.cast(arrPtr).add((short) 2, payload); 247 // 3 - tag 248 KMArray.cast(arrPtr).add((short) 3, signature); 249 return arrPtr; 250 } 251 252 /** 253 * Constructs array based on the tag values provided. 254 * 255 * @param tag array of tag values to be constructed. 256 * @param includeTestMode flag which indicates if TEST_COSE_KEY should be included or not. 257 * @return instance of KMArray. 258 */ handleCosePairTags( short[] tag, short[] keyValues, short valueIndex, boolean includeTestMode)259 private static short handleCosePairTags( 260 short[] tag, short[] keyValues, short valueIndex, boolean includeTestMode) { 261 short index = 0; 262 // var is used to calculate the length of the array. 263 short var = 0; 264 short tagLen = (short) tag.length; 265 // var is used to calculate the length of the array. 266 while (index < tagLen) { 267 if (keyValues[index] != KMType.INVALID_VALUE) { 268 keyValues[(short) (index + valueIndex)] = 269 buildCosePairTag((byte) tag[index], keyValues[index]); 270 var++; 271 } 272 index++; 273 } 274 var += includeTestMode ? 1 : 0; 275 short arrPtr = KMArray.instance(var); 276 index = 0; 277 // var is used to index the array. 278 var = 0; 279 while (index < tagLen) { 280 if (keyValues[(short) (index + valueIndex)] != KMType.INVALID_VALUE) { 281 KMArray.cast(arrPtr).add(var++, keyValues[(short) (index + valueIndex)]); 282 } 283 index++; 284 } 285 return arrPtr; 286 } 287 288 /** 289 * Constructs the COSE_sign1 payload for certificate. 290 * 291 * @param issuer instance of KMCosePairTextStringTag which contains issuer value. 292 * @param subject instance of KMCosePairTextStringTag which contains subject value. 293 * @param subPublicKey instance of KMCosePairByteBlobTag which contains encoded KMCoseKey. 294 * @param keyUsage instance of KMCosePairByteBlobTag which contains key usage value. 295 * @return instance of KMArray. 296 */ constructCoseCertPayload( short issuer, short subject, short subPublicKey, short keyUsage)297 public static short constructCoseCertPayload( 298 short issuer, short subject, short subPublicKey, short keyUsage) { 299 short certPayload = KMArray.instance((short) 4); 300 KMArray.cast(certPayload).add((short) 0, issuer); 301 KMArray.cast(certPayload).add((short) 1, subject); 302 KMArray.cast(certPayload).add((short) 2, subPublicKey); 303 KMArray.cast(certPayload).add((short) 3, keyUsage); 304 certPayload = KMCoseCertPayload.instance(certPayload); 305 KMCoseCertPayload.cast(certPayload).canonicalize(); 306 return certPayload; 307 } 308 309 /** 310 * Construct headers structure. Headers can be part of COSE_Sign1, COSE_Encrypt, COSE_Mac0 and 311 * COSE_Key. 312 * 313 * @param alg instance of either KMNInteger or KMInteger, based on the sign of algorithm value. 314 * @param keyId instance of KMByteBlob which contains the key identifier. 315 * @param iv instance of KMByteblob which contains the iv buffer. 316 * @param ephemeralKey instance of KMCoseKey. 317 * @return instance of KMCoseHeaders. 318 */ constructHeaders( short[] buff, short alg, short keyId, short iv, short ephemeralKey)319 public static short constructHeaders( 320 short[] buff, short alg, short keyId, short iv, short ephemeralKey) { 321 buff[0] = alg; 322 buff[1] = keyId; 323 buff[2] = iv; 324 buff[3] = ephemeralKey; 325 for (short i = 4; i < 8; i++) { 326 buff[i] = KMType.INVALID_VALUE; 327 } 328 short ptr = handleCosePairTags(COSE_HEADER_LABELS, buff, (short) 4, false); 329 ptr = KMCoseHeaders.instance(ptr); 330 KMCoseHeaders.cast(ptr).canonicalize(); 331 return ptr; 332 } 333 334 /** 335 * Construct Recipients structure for COSE_Encrypt message. 336 * 337 * @param protectedHeaders instance of KMByteBlob which contains encoded KMCoseHeaders. 338 * @param unprotectedHeaders instance of KMCoseHeaders. 339 * @param cipherText instance of KMSimple 340 * @return instance of KMArray. 341 */ constructRecipientsStructure( short protectedHeaders, short unprotectedHeaders, short cipherText)342 public static short constructRecipientsStructure( 343 short protectedHeaders, short unprotectedHeaders, short cipherText) { 344 // recipients : [+COSE_recipient] 345 // COSE_recipient = [ 346 // Headers, 347 // ciphertext : bstr / nil, 348 // ? recipients : [+COSE_recipient] 349 // ] 350 short arrPtr = KMArray.instance(COSE_ENCRYPT_RECIPIENT_ENTRY_COUNT); 351 // 1 - protected headers 352 KMArray.cast(arrPtr).add((short) 0, protectedHeaders); 353 // 2 - unprotected headers 354 KMArray.cast(arrPtr).add((short) 1, unprotectedHeaders); 355 // 2 - payload 356 KMArray.cast(arrPtr).add((short) 2, cipherText); 357 358 short recipientsArrayPtr = KMArray.instance((short) 1); 359 KMArray.cast(recipientsArrayPtr).add((short) 0, arrPtr); 360 return recipientsArrayPtr; 361 } 362 363 /** 364 * Construct Encrypt structure required for COSE_Encrypt message. 365 * 366 * @param protectedHeader instance of KMByteBlob which wraps KMCoseHeaders. 367 * @param aad instance of KMByteBlob. 368 * @return instance of KMArray. 369 */ constructCoseEncryptStructure(short protectedHeader, short aad)370 public static short constructCoseEncryptStructure(short protectedHeader, short aad) { 371 // Enc_structure = [ 372 // context : "Encrypt" / "Encrypt0" / "Enc_Recipient" / 373 // "Mac_Recipient" / "Rec_Recipient", 374 // protected : empty_or_serialized_map, 375 // external_aad : bstr 376 // ] 377 short arrPtr = KMArray.instance(COSE_ENCRYPT_STRUCTURE_ENTRY_COUNT); 378 // 1 - protected headers 379 KMArray.cast(arrPtr) 380 .add( 381 (short) 0, 382 KMTextString.instance( 383 KMCose.ENCRYPT_CONTEXT, (short) 0, (short) KMCose.ENCRYPT_CONTEXT.length)); 384 // 2 - unprotected headers 385 KMArray.cast(arrPtr).add((short) 1, protectedHeader); 386 // 2 - payload 387 KMArray.cast(arrPtr).add((short) 2, aad); 388 return arrPtr; 389 } 390 391 /** 392 * Constructs COSE_Encrypt message. 393 * 394 * @param protectedHeader instance of KMByteBlob which wraps KMCoseHeaders. 395 * @param unProtectedHeader instance of KMCoseHeaders. 396 * @param cipherText instance of KMByteBlob containing the cipher text. 397 * @param recipients instance of KMArray containing the recipients instance 398 * @return instance of KMArray. 399 */ constructCoseEncrypt( short protectedHeader, short unProtectedHeader, short cipherText, short recipients)400 public static short constructCoseEncrypt( 401 short protectedHeader, short unProtectedHeader, short cipherText, short recipients) { 402 // COSE_Encrypt = [ 403 // protectedHeader, 404 // unprotectedHeader, 405 // ciphertext : bstr / nil, 406 // recipients : [+COSE_recipient] 407 // ] 408 short arrPtr = KMArray.instance(KMCose.COSE_ENCRYPT_ENTRY_COUNT); 409 // 1 - protected headers 410 KMArray.cast(arrPtr).add((short) 0, protectedHeader); 411 // 2 - unprotected headers 412 KMArray.cast(arrPtr).add((short) 1, unProtectedHeader); 413 // 2 - payload 414 KMArray.cast(arrPtr).add((short) 2, cipherText); 415 // 3 - tag 416 KMArray.cast(arrPtr).add((short) 3, recipients); 417 return arrPtr; 418 } 419 420 /** 421 * Constructs the instance of KMCosePair*Tag. 422 * 423 * @param key value of the key. 424 * @param valuePtr instance of one of KMType. 425 * @return instance of KMCosePair*Value object. 426 */ buildCosePairTag(byte key, short valuePtr)427 public static short buildCosePairTag(byte key, short valuePtr) { 428 short type = KMType.getType(valuePtr); 429 short keyPtr; 430 if (key < 0) { 431 keyPtr = KMNInteger.uint_8(key); 432 } else { 433 keyPtr = KMInteger.uint_8(key); 434 } 435 switch (type) { 436 case KMType.INTEGER_TYPE: 437 return KMCosePairIntegerTag.instance(keyPtr, valuePtr); 438 case KMType.NEG_INTEGER_TYPE: 439 return KMCosePairNegIntegerTag.instance(keyPtr, valuePtr); 440 case KMType.BYTE_BLOB_TYPE: 441 return KMCosePairByteBlobTag.instance(keyPtr, valuePtr); 442 case KMType.TEXT_STRING_TYPE: 443 return KMCosePairTextStringTag.instance(keyPtr, valuePtr); 444 case KMType.COSE_KEY_TYPE: 445 return KMCosePairCoseKeyTag.instance(keyPtr, valuePtr); 446 default: 447 ISOException.throwIt(ISO7816.SW_DATA_INVALID); 448 return 0; 449 } 450 } 451 452 /** 453 * Constructs a CoseKey with the provided input parameters. Note that construction of the key_ops 454 * label is not needed to be supported. In the KeyMint2.0 specifications: The CoseKey inside 455 * MacedPublicKeys and DiceCertChain does not have key_ops label. 456 * 457 * @param keyType Instance of the identification of the key type. 458 * @param keyId Instance of key identification value. 459 * @param keyAlg Instance of the algorithm that is used with this key. 460 * @param curve Instance of the EC curve that is used with this key. 461 * @param pubKey Buffer containing the public key. 462 * @param pubKeyOff Start offset of the buffer. 463 * @param pubKeyLen Length of the public key. 464 * @param privKeyPtr Instance of the private key. 465 * @param testMode Represents if key is used in test mode or production mode. 466 * @return Instance of the CoseKey structure. 467 */ constructCoseKey( short[] buff, short keyType, short keyId, short keyAlg, short curve, byte[] pubKey, short pubKeyOff, short pubKeyLen, short privKeyPtr, boolean testMode)468 public static short constructCoseKey( 469 short[] buff, 470 short keyType, 471 short keyId, 472 short keyAlg, 473 short curve, 474 byte[] pubKey, 475 short pubKeyOff, 476 short pubKeyLen, 477 short privKeyPtr, 478 boolean testMode) { 479 if (pubKey[pubKeyOff] == 0x04) { // uncompressed format 480 pubKeyOff += 1; 481 pubKeyLen -= 1; 482 } 483 pubKeyLen = (short) (pubKeyLen / 2); 484 short xPtr = KMByteBlob.instance(pubKey, pubKeyOff, pubKeyLen); 485 short yPtr = KMByteBlob.instance(pubKey, (short) (pubKeyOff + pubKeyLen), pubKeyLen); 486 short coseKey = 487 constructCoseKey(buff, keyType, keyId, keyAlg, curve, xPtr, yPtr, privKeyPtr, testMode); 488 KMCoseKey.cast(coseKey).canonicalize(); 489 return coseKey; 490 } 491 492 /** 493 * Constructs the cose key based on input parameters supplied. All the parameters must be 494 * instantiated from either KMInteger or KMNInteger or KMByteblob types. 495 * 496 * @param keyType instance of KMInteger/KMNInteger which holds valid COSE key types. 497 * @param keyId instance of KMByteBlob which holds key identifier value. 498 * @param keyAlg instance of KMInteger/KMNInteger which holds valid COSE key algorithm. 499 * @param curve instance of KMInteger/KMNInteger which holds valid COSE EC curve. 500 * @param pubX instance of KMByteBlob which holds EC public key's x value. 501 * @param pubY instance of KMByteBlob which holds EC public key's y value. 502 * @param priv instance of KMByteBlob which holds EC private value. 503 * @param includeTestKey flag which identifies whether to construct test key or production key. 504 * @return instance of the KMCoseKey object. 505 */ constructCoseKey( short[] buff, short keyType, short keyId, short keyAlg, short curve, short pubX, short pubY, short priv, boolean includeTestKey)506 public static short constructCoseKey( 507 short[] buff, 508 short keyType, 509 short keyId, 510 short keyAlg, 511 short curve, 512 short pubX, 513 short pubY, 514 short priv, 515 boolean includeTestKey) { 516 short valueIndex = 7; 517 buff[0] = keyType; 518 buff[1] = keyId; 519 buff[2] = keyAlg; 520 buff[3] = curve; 521 buff[4] = pubX; 522 buff[5] = pubY; 523 buff[6] = priv; 524 for (short i = valueIndex; i < 16; i++) { 525 buff[i] = KMType.INVALID_VALUE; 526 } 527 short arrPtr = handleCosePairTags(COSE_KEY_LABELS, buff, valueIndex, includeTestKey); 528 if (includeTestKey) { 529 short testKey = 530 KMCosePairSimpleValueTag.instance( 531 KMNInteger.uint_32(KMCose.COSE_TEST_KEY, (short) 0), 532 KMSimpleValue.instance(KMSimpleValue.NULL)); 533 KMArray.cast(arrPtr).add((short) (KMArray.cast(arrPtr).length() - 1), testKey); 534 } 535 arrPtr = KMCoseKey.instance(arrPtr); 536 KMCoseKey.cast(arrPtr).canonicalize(); 537 return arrPtr; 538 } 539 540 /** 541 * Constructs key derivation context which is required to compute HKDF. 542 * 543 * @param publicKeyA public key buffer from the first party. 544 * @param publicKeyAOff start position of the public key buffer from first party. 545 * @param publicKeyALen length of the public key buffer from first party. 546 * @param publicKeyB public key buffer from the second party. 547 * @param publicKeyBOff start position of the public key buffer from second party. 548 * @param publicKeyBLen length of the public key buffer from second party. 549 * @param senderIsA true if caller is first party, false if caller is second party. 550 * @return instance of KMArray. 551 */ constructKdfContext( byte[] publicKeyA, short publicKeyAOff, short publicKeyALen, byte[] publicKeyB, short publicKeyBOff, short publicKeyBLen, boolean senderIsA)552 public static short constructKdfContext( 553 byte[] publicKeyA, 554 short publicKeyAOff, 555 short publicKeyALen, 556 byte[] publicKeyB, 557 short publicKeyBOff, 558 short publicKeyBLen, 559 boolean senderIsA) { 560 short index = 0; 561 // Prepare sender info 562 short senderInfo = KMArray.instance((short) 3); 563 KMArray.cast(senderInfo) 564 .add(index++, KMByteBlob.instance(client, (short) 0, (short) client.length)); 565 KMArray.cast(senderInfo).add(index++, KMByteBlob.instance((short) 0)); 566 KMArray.cast(senderInfo) 567 .add( 568 index, 569 senderIsA 570 ? KMByteBlob.instance(publicKeyA, publicKeyAOff, publicKeyALen) 571 : KMByteBlob.instance(publicKeyB, publicKeyBOff, publicKeyBLen)); 572 573 // Prepare recipient info 574 index = 0; 575 short recipientInfo = KMArray.instance((short) 3); 576 KMArray.cast(recipientInfo) 577 .add(index++, KMByteBlob.instance(server, (short) 0, (short) server.length)); 578 KMArray.cast(recipientInfo).add(index++, KMByteBlob.instance((short) 0)); 579 KMArray.cast(recipientInfo) 580 .add( 581 index, 582 senderIsA 583 ? KMByteBlob.instance(publicKeyB, publicKeyBOff, publicKeyBLen) 584 : KMByteBlob.instance(publicKeyA, publicKeyAOff, publicKeyALen)); 585 586 // supply public info 587 index = 0; 588 short publicInfo = KMArray.instance((short) 2); 589 KMArray.cast(publicInfo).add(index++, KMInteger.uint_16(AES_GCM_KEY_SIZE_BITS)); 590 KMArray.cast(publicInfo).add(index, KMByteBlob.instance((short) 0)); 591 592 // construct kdf context 593 index = 0; 594 short arrPtr = KMArray.instance((short) 4); 595 KMArray.cast(arrPtr).add(index++, KMInteger.uint_8(COSE_ALG_AES_GCM_256)); 596 KMArray.cast(arrPtr).add(index++, senderInfo); 597 KMArray.cast(arrPtr).add(index++, recipientInfo); 598 KMArray.cast(arrPtr).add(index, publicInfo); 599 600 return arrPtr; 601 } 602 } 603