Search in sources :

Example 11 with TlvException

use of es.gob.jmulticard.asn1.TlvException in project jmulticard by ctt-gob-es.

the class DerBoolean method decodeValue.

@Override
protected void decodeValue() throws Asn1Exception, TlvException {
    final Tlv tmpTlv = new Tlv(this.getRawDerValue());
    checkTag(tmpTlv.getTag());
    this.booleanValue = Boolean.valueOf(tmpTlv.getValue()[0] == (byte) 0x00);
}
Also used : Tlv(es.gob.jmulticard.asn1.Tlv)

Example 12 with TlvException

use of es.gob.jmulticard.asn1.TlvException in project jmulticard by ctt-gob-es.

the class OctectString method decodeValue.

@Override
protected void decodeValue() throws TlvException {
    final Tlv tlv = new Tlv(this.getRawDerValue());
    if (TAG_OCTECTSTRING != tlv.getTag()) {
        throw new TlvException(// $NON-NLS-1$
        "Se esperaba un TLV de tipo OctectString pero se ha encontrado uno de tipo " + HexUtils.hexify(new byte[] { tlv.getTag() }, false));
    }
    this.value = tlv.getValue();
}
Also used : TlvException(es.gob.jmulticard.asn1.TlvException) Tlv(es.gob.jmulticard.asn1.Tlv)

Example 13 with TlvException

use of es.gob.jmulticard.asn1.TlvException in project jmulticard by ctt-gob-es.

the class Record method decodeValue.

@Override
protected void decodeValue() throws Asn1Exception, TlvException {
    if (getRawDerValue().length == 0) {
        // $NON-NLS-1$
        throw new Asn1Exception("El valor del objeto ASN.1 esta vacio");
    }
    int offset = 0;
    Tlv tlv;
    byte[] remainingBytes;
    DecoderObject tmpDo;
    for (int i = 0; i < this.elementsTypes.length; i++) {
        try {
            remainingBytes = new byte[getRawDerValue().length - offset];
            System.arraycopy(getRawDerValue(), offset, remainingBytes, 0, remainingBytes.length);
            tlv = new Tlv(remainingBytes);
            try {
                tmpDo = this.elementsTypes[i].getElementType().getConstructor().newInstance();
            } catch (final Exception e) {
                throw new Asn1Exception(// $NON-NLS-1$
                "No se ha podido instanciar un " + this.elementsTypes[i].getElementType().getName() + " en la posicion " + Integer.toString(i) + " del registro: " + // $NON-NLS-1$ //$NON-NLS-2$
                e, // $NON-NLS-1$ //$NON-NLS-2$
                e);
            }
            tmpDo.checkTag(tlv.getTag());
        } catch (final Exception e) {
            if (this.elementsTypes[i].isOptional()) {
                // Como no ha avanzado el offset, se reutilizara el tipo en el proximo elemento
                continue;
            }
            // $NON-NLS-1$ //$NON-NLS-2$
            throw new Asn1Exception("Error en el elemento " + i + " del registro ASN.1: " + e, e);
        }
        offset = offset + tlv.getBytes().length;
        tmpDo.setDerValue(tlv.getBytes());
        this.elements.add(tmpDo);
    }
}
Also used : DecoderObject(es.gob.jmulticard.asn1.DecoderObject) Asn1Exception(es.gob.jmulticard.asn1.Asn1Exception) TlvException(es.gob.jmulticard.asn1.TlvException) Asn1Exception(es.gob.jmulticard.asn1.Asn1Exception) Tlv(es.gob.jmulticard.asn1.Tlv)

Example 14 with TlvException

use of es.gob.jmulticard.asn1.TlvException in project jmulticard by ctt-gob-es.

the class Utf8String method decodeValue.

@Override
protected void decodeValue() throws Asn1Exception, TlvException {
    final Tlv tlv = new Tlv(this.getRawDerValue());
    checkTag(tlv.getTag());
    this.stringValue = new String(tlv.getValue(), StandardCharsets.UTF_8);
}
Also used : Tlv(es.gob.jmulticard.asn1.Tlv)

Example 15 with TlvException

use of es.gob.jmulticard.asn1.TlvException in project jmulticard by ctt-gob-es.

the class PaceChannelHelper method openPaceChannel.

/**
 * Abre un canal PACE.
 * @param cla Clase de APDU para los comandos de establecimiento de canal.
 * @param pi Valor de inicializaci&oacute;n del canal. Puede ser un CAN
 *           (<i>Card Access Number</i>) o una MRZ (<i>Machine Readable Zone</i>).
 * @param conn Conexi&oacute;n hacia la tarjeta inteligente.
 * @param cryptoHelper Clase para la realizaci&oacute;n de operaciones criptogr&aacute;ficas auxiliares.
 * @return SecureMessaging Objeto para el env&iacute;o de mensajes seguros a trav&eacute;s de canal PACE.
 * @throws ApduConnectionException Si hay problemas de conexi&oacute;n con la tarjeta.
 * @throws PaceException Si hay problemas en la apertura del canal.
 */
public static SecureMessaging openPaceChannel(final byte cla, final PaceInitializer pi, final ApduConnection conn, final CryptoHelper cryptoHelper) throws ApduConnectionException, PaceException {
    if (conn == null) {
        throw new IllegalArgumentException(// $NON-NLS-1$
        "El canal de conexion no puede ser nulo");
    }
    if (pi == null) {
        throw new IllegalArgumentException(// $NON-NLS-1$
        "Es necesario proporcionar un inicializador para abrir canal PACE");
    }
    if (cryptoHelper == null) {
        throw new IllegalArgumentException(// $NON-NLS-1$
        "El CryptoHelper no puede ser nulo");
    }
    if (!conn.isOpen()) {
        conn.open();
    }
    ResponseApdu res;
    CommandApdu comm;
    // 1.3.2 - Establecemos el algoritmo para PACE con el comando MSE Set:
    comm = new MseSetPaceAlgorithmApduCommand(cla, MseSetPaceAlgorithmApduCommand.PaceAlgorithmOid.PACE_ECDH_GM_AES_CBC_CMAC128, pi.getPasswordType(), MseSetPaceAlgorithmApduCommand.PaceAlgorithmParam.BRAINPOOL_256_R1);
    res = conn.transmit(comm);
    if (!res.isOk()) {
        throw new PaceException(res.getStatusWord(), comm, // $NON-NLS-1$
        "Error estableciendo el algoritmo del protocolo PACE.");
    }
    // 1.3.3 - Primer comando General Autenticate - Get Nonce
    comm = new GeneralAuthenticateApduCommand((byte) 0x10, new byte[] { (byte) 0x7C, (byte) 0x00 });
    res = conn.transmit(comm);
    if (!res.isOk()) {
        throw new PaceException(res.getStatusWord(), comm, // $NON-NLS-1$
        "Error solicitando el aleatorio de calculo PACE (Nonce)");
    }
    // Calcular nonce devuelto por la tarjeta que se empleara en los calculos
    final byte[] nonce;
    try {
        nonce = new Tlv(new Tlv(res.getData()).getValue()).getValue();
    } catch (final TlvException e) {
        throw new PaceException(// $NON-NLS-1$ //$NON-NLS-2$
        "El aleatorio de calculo PACE (Nonce) obtenido (" + HexUtils.hexify(res.getData(), true) + ") no sigue el formato esperado: " + e, // $NON-NLS-1$ //$NON-NLS-2$
        e);
    }
    // Calcular sk = SHA-1( CAN || 00000003 );
    // La clave son los 16 bytes MSB del hash
    final byte[] sk = new byte[16];
    try {
        System.arraycopy(cryptoHelper.digest(CryptoHelper.DigestAlgorithm.SHA1, HexUtils.concatenateByteArrays(pi.getBytes(), CAN_MRZ_PADDING)), 0, sk, 0, 16);
    } catch (final IOException e) {
        throw new PaceException(// $NON-NLS-1$
        "Error obteniendo el 'sk' a partir del CAN: " + e, // $NON-NLS-1$
        e);
    }
    // Calcular secret = AES_Dec(nonce,sk);
    final byte[] secret_nonce;
    try {
        secret_nonce = cryptoHelper.aesDecrypt(nonce, new byte[0], sk);
    } catch (final Exception e) {
        throw new PaceException(// $NON-NLS-1$
        "Error descifranco el 'nonce': " + e, // $NON-NLS-1$
        e);
    }
    // 1.3.4 - Segundo comando General Autenticate - Map Nonce
    // Generamos un par de claves efimeras EC para el DH
    // $NON-NLS-1$
    final X9ECParameters ecdhParameters = TeleTrusTNamedCurves.getByName("brainpoolp256r1");
    final ECPoint pointG = ecdhParameters.getG();
    final Fp curve = (org.spongycastle.math.ec.ECCurve.Fp) ecdhParameters.getCurve();
    // La privada del terminal se genera aleatoriamente (PrkIFDDH1)
    // La publica de la tarjeta sera devuelta por ella misma al enviar nuesra publica (pukIFDDH1)
    final Random rnd = new Random();
    rnd.setSeed(rnd.nextLong());
    final byte[] x1 = new byte[curve.getFieldSize() / 8];
    rnd.nextBytes(x1);
    final BigInteger PrkIFDDH1 = new BigInteger(1, x1);
    // Enviamos nuestra clave publica (pukIFDDH1 = G*PrkIFDDH1)
    final ECPoint pukIFDDH1 = pointG.multiply(PrkIFDDH1);
    Tlv tlv = new Tlv(TAG_DYNAMIC_AUTHENTICATION_DATA, new Tlv(TAG_GEN_AUTH_2, pukIFDDH1.getEncoded(false)).getBytes());
    // ... Y la enviamos a la tarjeta
    comm = new GeneralAuthenticateApduCommand((byte) 0x10, tlv.getBytes());
    res = conn.transmit(comm);
    if (!res.isOk()) {
        throw new PaceException(res.getStatusWord(), comm, // $NON-NLS-1$
        "Error mapeando el aleatorio de calculo PACE (Nonce)");
    }
    // Se obtiene la clave publica de la tarjeta
    final byte[] pukIccDh1;
    try {
        pukIccDh1 = unwrapEcKey(res.getData());
    } catch (final Exception e) {
        throw new PaceException(// $NON-NLS-1$
        "Error obteniendo la clave efimera EC publica de la tarjeta: " + e, // $NON-NLS-1$
        e);
    }
    // calcular blinding point H = PrkIFDDH1 * PukICCDH1
    final ECPoint y1FromG = byteArrayToECPoint(pukIccDh1, curve);
    // Calculamos el punto H secreto
    final ECPoint SharedSecret_H = y1FromG.multiply(PrkIFDDH1);
    // Se calcula el nuevo punto G' = nonce*G + H
    final BigInteger ms = new BigInteger(1, secret_nonce);
    final ECPoint g_temp = pointG.multiply(ms);
    final ECPoint newPointG = g_temp.add(SharedSecret_H);
    // 1.3.5 Tercer comando General Authenticate
    // Se calcula la coordenada X de G' y generamos con la tarjeta un nuevo acuerdo de claves
    // La privada del terminal se genera aleatoriamente (PrkIFDDH2)
    // La publica de la tarjeta sera devuelta por ella misma al enviar nuesra publica (pukIFDDH2)
    final byte[] x2 = new byte[curve.getFieldSize() / 8];
    rnd.setSeed(rnd.nextLong());
    rnd.nextBytes(x2);
    final BigInteger PrkIFDDH2 = new BigInteger(1, x2);
    // Enviamos nuestra clave publica (pukIFDDH2 = G'*PrkIFDDH2)
    final ECPoint pukIFDDH2 = newPointG.multiply(PrkIFDDH2);
    // ... La metemos en un TLV de autenticacion ...
    tlv = new Tlv(TAG_DYNAMIC_AUTHENTICATION_DATA, new Tlv(TAG_GEN_AUTH_3, pukIFDDH2.getEncoded(false)).getBytes());
    comm = new GeneralAuthenticateApduCommand((byte) 0x10, tlv.getBytes());
    res = conn.transmit(comm);
    // Se obtiene la clave publica de la tarjeta (pukIccDh2) que es la coordenada Y del nuevo Punto G'
    final byte[] pukIccDh2;
    try {
        pukIccDh2 = unwrapEcKey(res.getData());
    } catch (final Exception e) {
        throw new PaceException(// $NON-NLS-1$
        "Error obteniendo la clave efimera EC publica de la tarjeta: " + e, // $NON-NLS-1$
        e);
    }
    final ECPoint y2FromNewG = byteArrayToECPoint(pukIccDh2, curve);
    // Se calcula el secreto k = PukICCDH2 * PrkIFDDH2
    final ECPoint.Fp SharedSecret_K = (org.spongycastle.math.ec.ECPoint.Fp) y2FromNewG.multiply(PrkIFDDH2);
    final byte[] secretK = bigIntToByteArray(SharedSecret_K.normalize().getXCoord().toBigInteger());
    // 1.3.6 Cuarto comando General Authenticate
    // Se validan las claves de sesion generadas en el paso anterior,
    // por medio de un MAC que calcula el terminal y comprueba la tarjeta,
    // la cual devolvera un segundo MAC.
    // Calcular kenc = SHA-1( k || 00000001 );
    final byte[] kenc = new byte[16];
    try {
        System.arraycopy(cryptoHelper.digest(CryptoHelper.DigestAlgorithm.SHA1, HexUtils.concatenateByteArrays(secretK, KENC_PADDING)), 0, kenc, 0, 16);
    } catch (final IOException e) {
        throw new PaceException(// $NON-NLS-1$
        "Error obteniendo el 'kenc' a partir del CAN: " + e, // $NON-NLS-1$
        e);
    }
    // Calcular kmac = SHA-1( k || 00000002 );
    final byte[] kmac = new byte[16];
    try {
        System.arraycopy(cryptoHelper.digest(CryptoHelper.DigestAlgorithm.SHA1, HexUtils.concatenateByteArrays(secretK, KMAC_PADDING)), 0, kmac, 0, 16);
    } catch (final IOException e) {
        throw new PaceException(// $NON-NLS-1$
        "Error obteniendo el 'kmac' a partir del CAN: " + e, // $NON-NLS-1$
        e);
    }
    // Elimina el byte '04' del inicio que es el indicador de punto descomprimido
    final byte[] pukIccDh2Descompressed = new byte[pukIccDh2.length - 1];
    System.arraycopy(pukIccDh2, 1, pukIccDh2Descompressed, 0, pukIccDh2.length - 1);
    // Se calcula el Mac del terminal: data = '7f494F06' + oid + '864104' + PukICCDH2;
    final byte[] data = HexUtils.concatenateByteArrays(MAC_PADDING, HexUtils.concatenateByteArrays(MseSetPaceAlgorithmApduCommand.PaceAlgorithmOid.PACE_ECDH_GM_AES_CBC_CMAC128.getBytes(), HexUtils.concatenateByteArrays(MAC2_PADDING, pukIccDh2Descompressed)));
    byte[] mac8bytes;
    try {
        mac8bytes = cryptoHelper.doAesCmac(data, kmac);
    } catch (final Exception e) {
        throw new PaceException(// $NON-NLS-1$
        "Error descifrando el 'nonce': " + e, // $NON-NLS-1$
        e);
    }
    // ... La metemos en un TLV de autenticacion ...
    tlv = new Tlv(TAG_DYNAMIC_AUTHENTICATION_DATA, new Tlv(TAG_GEN_AUTH_4, mac8bytes).getBytes());
    // Se envia el comando General Authenticate y se recupera el MAC devuelto por la tarjeta.
    comm = new GeneralAuthenticateApduCommand((byte) 0x00, tlv.getBytes());
    res = conn.transmit(comm);
    // Se obtiene un MAC con respuesta 90-00 indicando que se ha establecido el canal correctamente
    if (!res.isOk()) {
        throw new PaceException(res.getStatusWord(), comm, // $NON-NLS-1$
        "Error estableciendo el algoritmo del protocolo PACE.");
    }
    // Se inicializa el contador de secuencia a ceros
    final byte[] ssc = new byte[16];
    Arrays.fill(ssc, (byte) 0);
    // $NON-NLS-1$
    LOGGER.info("Canal Pace abierto");
    LOGGER.info(// $NON-NLS-1$
    "\nKenc: " + HexUtils.hexify(kenc, true) + "Kmac: " + // $NON-NLS-1$
    HexUtils.hexify(kmac, true) + "Ssc: " + // $NON-NLS-1$
    HexUtils.hexify(ssc, true));
    final AmCryptoProvider crypto = new AmAESCrypto();
    return new SecureMessaging(crypto, kenc, kmac, new byte[crypto.getBlockSize()]);
}
Also used : CommandApdu(es.gob.jmulticard.apdu.CommandApdu) SecureMessaging(es.gob.jmulticard.de.tsenger.androsmex.iso7816.SecureMessaging) AmAESCrypto(es.gob.jmulticard.de.tsenger.androsmex.crypto.AmAESCrypto) X9ECParameters(org.spongycastle.asn1.x9.X9ECParameters) ResponseApdu(es.gob.jmulticard.apdu.ResponseApdu) Fp(org.spongycastle.math.ec.ECCurve.Fp) IOException(java.io.IOException) ECPoint(org.spongycastle.math.ec.ECPoint) ApduConnectionException(es.gob.jmulticard.apdu.connection.ApduConnectionException) IOException(java.io.IOException) TlvException(es.gob.jmulticard.asn1.TlvException) AmCryptoProvider(es.gob.jmulticard.de.tsenger.androsmex.crypto.AmCryptoProvider) TlvException(es.gob.jmulticard.asn1.TlvException) Random(java.util.Random) MseSetPaceAlgorithmApduCommand(es.gob.jmulticard.apdu.iso7816four.pace.MseSetPaceAlgorithmApduCommand) GeneralAuthenticateApduCommand(es.gob.jmulticard.apdu.iso7816four.GeneralAuthenticateApduCommand) BigInteger(java.math.BigInteger) Tlv(es.gob.jmulticard.asn1.Tlv)

Aggregations

TlvException (es.gob.jmulticard.asn1.TlvException)10 Asn1Exception (es.gob.jmulticard.asn1.Asn1Exception)9 Tlv (es.gob.jmulticard.asn1.Tlv)8 ApduConnectionException (es.gob.jmulticard.apdu.connection.ApduConnectionException)4 DecoderObject (es.gob.jmulticard.asn1.DecoderObject)4 IOException (java.io.IOException)4 Cdf (es.gob.jmulticard.asn1.der.pkcs15.Cdf)3 InvalidCardException (es.gob.jmulticard.card.InvalidCardException)3 Location (es.gob.jmulticard.card.Location)3 FileNotFoundException (es.gob.jmulticard.card.iso7816four.FileNotFoundException)3 Iso7816FourCardException (es.gob.jmulticard.card.iso7816four.Iso7816FourCardException)3 CertificateException (java.security.cert.CertificateException)3 X509Certificate (java.security.cert.X509Certificate)3 CommandApdu (es.gob.jmulticard.apdu.CommandApdu)2 Odf (es.gob.jmulticard.asn1.der.pkcs15.Odf)2 Path (es.gob.jmulticard.asn1.der.pkcs15.Path)2 Pkcs15Cdf (es.gob.jmulticard.asn1.der.pkcs15.Pkcs15Cdf)2 PrKdf (es.gob.jmulticard.asn1.der.pkcs15.PrKdf)2 AuthenticationModeLockedException (es.gob.jmulticard.card.AuthenticationModeLockedException)2 BadPinException (es.gob.jmulticard.card.BadPinException)2