aboutsummaryrefslogtreecommitdiff
path: root/ready_se/google/keymint/KM200/Applet/AndroidSEProviderLib/src/com/android/javacard/seprovider/KMEcdsa256NoDigestSignature.java
blob: 83774ab8f7973581a1a1026cdd2592abc24e17b0 (plain)
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
/*
 * Copyright(C) 2020 The Android Open Source Project
 *
 * 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" (short)0IS,
 * 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.android.javacard.seprovider;

import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.Key;
import javacard.security.MessageDigest;
import javacard.security.Signature;
import javacardx.crypto.Cipher;

/**
 * This class provides support for ECDSA_NO_DIGEST signature algorithm. Added this because javacard
 * 3.0.5 does not support this
 */
public class KMEcdsa256NoDigestSignature extends Signature {

  public static final byte ALG_ECDSA_NODIGEST = (byte) 0x67;
  public static final byte MAX_NO_DIGEST_MSG_LEN = 32;
  private byte algorithm;
  private Signature inst;

  public KMEcdsa256NoDigestSignature(byte alg) {
    algorithm = alg;
    // There is no constant for no digest so ALG_ECDSA_SHA_256 is used. However,
    // signPreComputedHash is used for signing which is equivalent to no digest sign.
    inst = Signature.getInstance(Signature.ALG_ECDSA_SHA_256, false);
  }

  @Override
  public void init(Key key, byte b) throws CryptoException {
    inst.init(key, b);
  }

  @Override
  public void init(Key key, byte b, byte[] bytes, short i, short i1) throws CryptoException {
    inst.init(key, b, bytes, i, i1);
  }

  @Override
  public void setInitialDigest(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3)
      throws CryptoException {}

  @Override
  public byte getAlgorithm() {
    return algorithm;
  }

  @Override
  public byte getMessageDigestAlgorithm() {
    return MessageDigest.ALG_NULL;
  }

  @Override
  public byte getCipherAlgorithm() {
    return 0;
  }

  @Override
  public byte getPaddingAlgorithm() {
    return Cipher.PAD_NULL;
  }

  @Override
  public short getLength() throws CryptoException {
    return inst.getLength();
  }

  @Override
  public void update(byte[] message, short msgStart, short messageLength) throws CryptoException {
    // HAL accumulates the data and send it at finish operation.
  }

  @Override
  public short sign(byte[] bytes, short i, short i1, byte[] bytes1, short i2)
      throws CryptoException {
    try {
      if (i1 > MAX_NO_DIGEST_MSG_LEN) {
        CryptoException.throwIt(CryptoException.ILLEGAL_USE);
      }
      // add zeros to the left
      if (i1 < MAX_NO_DIGEST_MSG_LEN) {
        Util.arrayFillNonAtomic(
            KMAndroidSEProvider.getInstance().tmpArray,
            (short) 0,
            (short) MAX_NO_DIGEST_MSG_LEN,
            (byte) 0);
      }
      Util.arrayCopyNonAtomic(
          bytes,
          i,
          KMAndroidSEProvider.getInstance().tmpArray,
          (short) (MAX_NO_DIGEST_MSG_LEN - i1),
          i1);
      return inst.signPreComputedHash(
          KMAndroidSEProvider.getInstance().tmpArray,
          (short) 0,
          (short) MAX_NO_DIGEST_MSG_LEN,
          bytes1,
          i2);
    } finally {
      KMAndroidSEProvider.getInstance().clean();
    }
  }

  @Override
  public short signPreComputedHash(byte[] bytes, short i, short i1, byte[] bytes1, short i2)
      throws CryptoException {
    return inst.sign(bytes, i, i1, bytes1, i2);
  }

  @Override
  public boolean verify(byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3)
      throws CryptoException {
    // Verification is handled inside HAL
    return false;
  }

  @Override
  public boolean verifyPreComputedHash(
      byte[] bytes, short i, short i1, byte[] bytes1, short i2, short i3) throws CryptoException {
    // Verification is handled inside HAL
    return false;
  }
}