-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
apdu.js
78 lines (71 loc) · 2.45 KB
/
apdu.js
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
'use strict'
var trace = false
function formatResponse (apdu) {
return apdu.slice(0, apdu.length - 2).toString('hex') + (apdu.length === 2 ? '' : ' ') + apdu.slice(-2).toString('hex')
}
function formatCommand (apdu) {
if (apdu.length === 4) {
return apdu.toString('hex')
} else if (apdu.length >= 5) {
return apdu.slice(0, 4).toString('hex') + ' ' + apdu.slice(4, 5).toString('hex') + ' ' + apdu.slice(5, 5 + apdu[4]).toString('hex')
}
}
// given a function that returns promises for APDU-s as raw bytes
// wrap it with APDU semantics for GET RESPONSE handling
function apdufy (transmit) {
return function (apdu) {
// Allow to transmit hex strings
if (typeof apdu === 'string') {
apdu = Buffer.from(apdu, 'hex')
}
return new Promise(function (resolve, reject) {
var start = new Date().getTime()
if (trace) { console.log('A>> ' + formatCommand(apdu)) }
transmit(apdu).then(function (response) {
var sw = response.slice(-2)
if (sw[0] === 0x61) {
transmit(Buffer.from([0x00, 0xC0, 0x00, 0x00, sw[1]])).then(function (response) {
if (trace) {
var ms = new Date().getTime() - start
console.log('A<< (%d ms) %s', ms, formatResponse(response))
}
return resolve(response)
}).catch(function (reason) {
return reject(reason)
})
} else {
var ms = new Date().getTime() - start
if (trace) { console.log('A<< (%d ms) %s', ms, formatResponse(response)) }
return resolve(response)
}
}).catch(function (reason) {
return reject(reason)
})
})
}
}
// Given a APDU promise, resolve it and reject it if answer sw is not 0x9000 or "ok"
function check (p, ok) {
var oksw = []
if (typeof ok === 'number') { oksw.push(ok) }
if (oksw.indexOf(0x9000) === -1) { oksw.push(0x9000) }
return p.then(function (response) {
const sw = getsw(response)
if (oksw.indexOf(sw) === -1) {
throw new Error('APDU SW check failed, SW 0x' + sw.toString(16) + ' not in ' + oksw.map(function (x) { return '0x' + x.toString(16) }).join(' '))
} else {
return response
}
})
}
function getsw (response) {
var sw = response.slice(-2)
return (sw[0] << 8) | sw[1]
}
function getdata (response) {
return response.slice(0, response.length - 2)
}
module.exports.apdufy = apdufy
module.exports.check = check
module.exports.sw = getsw
module.exports.data = getdata