RfidResearchGroup / ChameleonUltra

The new generation chameleon based on NRF52840 makes the performance of card emulation more stable. And gave the chameleon the ability to read, write, and decrypt cards.
https://chameleonultra.com
GNU General Public License v3.0
838 stars 144 forks source link

Next release v2.0.0. Clarify protocol. Disruptive changes: see below #147

Closed doegox closed 10 months ago

doegox commented 11 months ago

This huge commit tries to enhance several things related to the fw/cli protocol. Generally, the idea is to be verbose, explicit and reuse conventions, in order to enhance code maintainability and understandability for the other contributors.

docs/protocol.md got heavily updated

Many commands have been renamed for consistency. you are invited to adapt your client for easier maintenance

Guidelines, also written in docs/protocol.md "New data payloads: guidelines for developers":

Disruptive changes:

For clients to detect Ultra/Lite with older firmwares, one can issue the GET_APP_VERSION and urge the user to flash his device if needed. On older firmwares, it will return a status=b'\x00' and data=b'\x00\x01' while up-to-date firmwares will return status=STATUS_DEVICE_SUCCESS and data greater or equal to b'\x01\x00' (v1.0).

Other changes: cf CHANGELOG, and probably a few small changes I forgot about..

github-actions[bot] commented 11 months ago

You are welcome to add an entry to the CHANGELOG.md as well

github-actions[bot] commented 11 months ago

Built artifacts for commit 963d4d62f1bc6da5a079ab7c67317c2530d2af95

Firmware

Client

xianglin1998 commented 11 months ago

A very perfect idea. I estimate that I will only be available next week to continue contributing, as I am too busy this week.

taichunmin commented 11 months ago

Should tag_type in DATA_CMD_GET_SLOT_INFO cmd response to be change to 2 bytes?

taichunmin commented 11 months ago

Should we rename the GET/SET_BLE_CONNECT_KEY_CONFIG to GET/SET_BLE_PAIRING_KEY_CONFIG ?

Because the cmd GET/SET_BLE_PAIRING_ENABLE using the word PAIRING.

doegox commented 11 months ago

Should we rename the GET/SET_BLE_CONNECT_KEY_CONFIG to GET/SET_BLE_PAIRING_KEY_CONFIG ?

Because the cmd GET/SET_BLE_PAIRING_ENABLE using the word PAIRING.

yes, or just GET/SET_BLE_PAIRING_KEY

taichunmin commented 11 months ago

Should 4002: MF1_SET_ANTI_COLLISION_INFO to be detele?

Should 4001: MF1_SET_ANTI_COLLISION_RES to be rename to MF1_SET_ANTI_COLL_DATA because of 4018: MF1_GET_ANTI_COLL_DATA?

taichunmin commented 11 months ago

The request frame of MF1_SET_ANTI_COLLISION_RES is inconsistent with response frame of MF1_GET_ANTI_COLL_DATA. Should we modify one of them?

MF1_SET_ANTI_COLLISION_RES: SAK (1 Byte) + ATQA (2 Byte) + UID (4, 7 or 10 Bytes) MF1_GET_ANTI_COLL_DATA: UID (10 Bytes) + UID Size (2 Bytes) + SAK (1 Byte) + ATQA (2 Bytes) + Unknown (1 Byte)

doegox commented 11 months ago

The request frame of MF1_SET_ANTI_COLLISION_RES is inconsistent with response frame of MF1_GET_ANTI_COLL_DATA. Should we modify one of them?

MF1_SET_ANTI_COLLISION_RES: SAK (1 Byte) + ATQA (2 Byte) + UID (4, 7 or 10 Bytes) MF1_GET_ANTI_COLL_DATA: UID (10 Bytes) + UID Size (2 Bytes) + SAK (1 Byte) + ATQA (2 Bytes) + Unknown (1 Byte)

and inconsistent with HF14A_SCAN which I'd like to simplify as well :) and allow for more than 1 tag.

So sth like

taichunmin commented 11 months ago

Also rename MF1_GET_BLOCK_ANTI_COLL_MODE and MF1_SET_BLOCK_ANTI_COLL_MODE to hf14a?

doegox commented 11 months ago

Also rename MF1_GET_BLOCK_ANTI_COLL_MODE and MF1_SET_BLOCK_ANTI_COLL_MODE to hf14a?

These ones are specific to tags storing their anticol data in a block, so only 4-byte MF1

augustozanellato commented 11 months ago

I wish I saw this before submitting my last PR lol, feel free to cherrypick stuff and merge it here

taichunmin commented 11 months ago

typo in PR description:

MF1_DARKSIDE_ACQUIRE response status is now HF_TAG_OK and darkside_status is returned in 1 byte of data. If OK, followed by 24 bytes as previously

It should be 32 bytes, not 24 bytes

taichunmin commented 11 months ago

The MF1_DARKSIDE_DETECT command in PR description is wrong. (Because of being removed)

doegox commented 11 months ago

Thank you @taichunmin ! I fixed both. In PR and in new commit.

Foxushka commented 10 months ago

image MF1_DETECT_SUPPORT will return status 1 if card doesn't support Mifare Classic (not 0 in .data[0])

doegox commented 10 months ago

image MF1_DETECT_SUPPORT will return status 1 if card doesn't support Mifare Classic (not 0 in .data[0])

ha yes indeed, data is redundant, I removed it, thanks

doegox commented 10 months ago

ok, so far, unless bugs, I think we're done with the protocol changes. The only non uniformity I see remaining is that some commands spread bits into bytes (much easier to parse in Python and probably not impacting much the comms) while some are using bitfields (mf1_get_detection_log because it's how it is stored in flash, and HF14A_RAW options). I don't have strong opinion on staying as such or moving in one or the other direction... Any comment ?

@GameTec-live @Foxushka @taichunmin @whywilson are you ready in your CLI/SDK for the merge of this PR?

BTW how could we make it easier ? It's hard to have to get all clients to be ready for the move exactly at the same moment. Having a way to indicate to your client to not upgrade the fw to the latest version unless the client got upgraded. Any suggestion how?

taichunmin commented 10 months ago

There are not many developers using the chameleon-ultra.js SDK yet, so this Pull Request has a small impact on my SDK.

xianglin1998 commented 10 months ago

Can we start iterating versions and have the app/client choose whether to update the device firmware based on the last supported device firmware version?

nemanjan00 commented 10 months ago

Looking at the API of github release creation, it does not seem to support any form of metadata, so I propose to use tags and semver.

x.y.z

x - breakage of compatibility of command y - new command z - bug fix

This way, they know that they need to take manual action on major (x)

augustozanellato commented 10 months ago

Looking at the API of github release creation, it does not seem to support any form of metadata, so I propose to use tags and semver.

semver implies releases, at the moment there haven’t been any releases except for the factory firmware. We’d probably have to start making periodic releases and tagging those with semver, while keeping the dev build as “unstable, you’re on your own, here be dragons”

whywilson commented 10 months ago

Can we start iterating versions and have the app/client choose whether to update the device firmware based on the last supported device firmware version?

Necessary. When users encounter problems, they can now only recommend updating to the latest firmware and app, but cannot directly locate firmware problems.

MTools Lite can have fast updates to the changes. It's time to implement.

doegox commented 10 months ago

Looking at the API of github release creation, it does not seem to support any form of metadata, so I propose to use tags and semver.

x.y.z

x - breakage of compatibility of command y - new command z - bug fix

This way, they know that they need to take manual action on major (x)

FW_VER_NUM of nRF SDK is only x.y (advertised over BLE & USB) and the fw can also provide its GIT_VERSION as per git describe --abbrev=7 --dirty --always --tags That's for the code itself.

Then for git releases we can use vx.y.z annotated tags, just make sure to have the same x and y as above...

I propose to:

doegox commented 10 months ago

I updated the proposal to avoid bumping versions to 2.0.0 and 3.0.0 one after the other

nemanjan00 commented 10 months ago

Maybe we can take version from latest git tag instead?

TAG=$(git describe --tags --abbrev=0 --match "v*.*") # match tag that looks like version

MAJOR=$(echo $TAG | cut -d "." -f1) # take first segment of tag
MAJOR=${MAJOR:1} # remove 'v'

MINOR=$(echo $TAG | cut -d "." -f2) # take second segment

echo $MAJOR.$MINOR

Something like this?

doegox commented 10 months ago

Hmm we may try but we need fallbacks for when compiling not from a repo. (source zip, source in distros (one day... :) )

For ref, here is how we do for Proxmark in Makefile and mkversion.sh

Knowing that here we would go for semver and we have automatic releases so the workflow creating releases must make sure the produced release source can compile and show decent version info.

Foxushka commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one)

@whywilson your app ready?

GameTec-live commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one)

@whywilson your app ready?

nope, sadly not... still some major bugs...

Foxushka commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one) @whywilson your app ready?

nope, sadly not... still some major bugs...

Not critical, anyway firmware should be merged firstly

doegox commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one) @whywilson your app ready?

nope, sadly not... still some major bugs...

Not critical, anyway firmware should be merged firstly

does MTools allow for fw upgrades too? If yes is it also automatic from latest commit? Else can we merge ?

doegox commented 10 months ago

@nemanjan00 I pushed mechanics in Makefile to get APP_FW major & minor. This does not solve yet the issue in source releases but one step after the other one :) Update: oops it breaks the CI...

whywilson commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one)

@whywilson your app ready?

nope, sadly not... still some major bugs...

Not critical, anyway firmware should be merged firstly

does MTools allow for fw upgrades too? If yes is it also automatic from latest commit? Else can we merge ?

No. MTools Lite works on Bluetooth. After merging the code, will the version number of fw be iterated normally? Or only determine the firmware version by git id for the moment?

doegox commented 10 months ago

From our side everything is ready, waiting for merge into main (as our app WILL require new protocol and won't work with earlier one)

@whywilson your app ready?

nope, sadly not... still some major bugs...

Not critical, anyway firmware should be merged firstly

does MTools allow for fw upgrades too? If yes is it also automatic from latest commit? Else can we merge ?

No. MTools Lite works on Bluetooth. After merging the code, will the version number of fw be iterated normally? Or only determine the firmware version by git id for the moment?

I'm trying to base the fw version x.y automatically on the latest existing git tag "vx.y.z" , which will be created manually at least every time the protocol changes (x+1 if breaking, y+1 if new command) but so far it fails in the CI... Despite fetch-depth: 0 it fetches with --depth=1 cf https://github.com/RfidResearchGroup/ChameleonUltra/actions/runs/6305449165/job/17118902995?pr=147#step:2:52 @augustozanellato any idea why and how to fix it ?

nemanjan00 commented 10 months ago

I am not a GitHub CI guy (I prefer GitLab), but, log

Job defined at: RfidResearchGroup/ChameleonUltra/.github/workflows/build_firmware.yml@refs/heads/main

makes it sound like you need to change script in main, it does not seem to want to use scripts from PR, probably for security reasons

doegox commented 10 months ago

I am not a GitHub CI guy (I prefer GitLab), but, log

Job defined at: RfidResearchGroup/ChameleonUltra/.github/workflows/build_firmware.yml@refs/heads/main

makes it sound like you need to change script in main, it does not seem to want to use scripts from PR, probably for security reasons

Strange, if I do a new branch from the PR, then it works fine https://github.com/RfidResearchGroup/ChameleonUltra/actions/runs/6305741100/job/17119709062 Uses: RfidResearchGroup/ChameleonUltra/.github/workflows/build_firmware.yml@refs/heads/test_again_ci

nemanjan00 commented 10 months ago

My experience with GH CI is very limited, but I assume it has something to do with branch being PR

doegox commented 10 months ago

Thanks, it should work once merged :) Release v2.0.0 is ready to be pushed.

nemanjan00 commented 10 months ago

I think it is due to pull_request_target

https://github.com/orgs/community/discussions/27084#discussioncomment-3254544

doegox commented 10 months ago

Release ready, preview available at https://github.com/doegox/ChameleonUltra/releases/tag/v2.0.0 @Foxushka @GameTec-live tell me when I can push it to the repo.

augustozanellato commented 10 months ago

I think it is due to pull_request_target

https://github.com/orgs/community/discussions/27084#discussioncomment-3254544

It indeed is. It was documented on the refactored ci PR. Tl;dr pull_request_target takes the workflows files from the pr target branch, so you can’t test CI changes before merging them. pull_request_target is required in order to have a token with write access that is used to push the builder docker image on PRs.

doegox commented 10 months ago

I think it is due to pull_request_target https://github.com/orgs/community/discussions/27084#discussioncomment-3254544

It indeed is. It was documented on the refactored ci PR. Tl;dr pull_request_target takes the workflows files from the pr target branch, so you can’t test CI changes before merging them. pull_request_target is required in order to have a token with write access that is used to push the builder docker image on PRs.

thanks for the explanation @augustozanellato ! I added a section in the yaml to build releases on vx.y.z tags as well : https://github.com/RfidResearchGroup/ChameleonUltra/pull/147/commits/099fb6b912eaf947fed736c7ed8970972c3308c5 tested on my fork : https://github.com/doegox/ChameleonUltra/releases/tag/v2.0.0 This looks ok for you ?

augustozanellato commented 10 months ago

I think it is due to pull_request_target https://github.com/orgs/community/discussions/27084#discussioncomment-3254544

It indeed is. It was documented on the refactored ci PR. Tl;dr pull_request_target takes the workflows files from the pr target branch, so you can’t test CI changes before merging them. pull_request_target is required in order to have a token with write access that is used to push the builder docker image on PRs.

thanks for the explanation @augustozanellato ! I added a section in the yaml to build releases on vx.y.z tags as well : 099fb6b tested on my fork : https://github.com/doegox/ChameleonUltra/releases/tag/v2.0.0 This looks ok for you ?

LGTM!

doegox commented 10 months ago

Apparently the GUI still needs some functional fixes so we'll wait a bit

Foxushka commented 10 months ago

What I skipped, why now git hash is v2.0.0? image I've downloaded from https://github.com/doegox/ChameleonUltra/releases/tag/v2.0.0

doegox commented 10 months ago

What I skipped, why now git hash is v2.0.0? image I've downloaded from https://github.com/doegox/ChameleonUltra/releases/tag/v2.0.0

Nothing changed, the git version string is the output of git describe --abbrev=7 --dirty --always --tags

$ git checkout main
Already on 'main'
Your branch is ahead of 'origin/main' by 40 commits.
  (use "git push" to publish your local commits)

$ git describe --abbrev=7 --dirty --always --tags
v2.0.0

$ echo foo > CHANGELOG.md 
$ git commit -a -m foo
[main 617d6d0] foo
 1 file changed, 1 insertion(+), 100 deletions(-)

$ git describe --abbrev=7 --dirty --always --tags
v2.0.0-1-g617d6d0

$ echo bar > CHANGELOG.md 

$ git describe --abbrev=7 --dirty --always --tags
v2.0.0-1-g617d6d0-dirty
Foxushka commented 10 months ago

So it won't cause issues later? Only one time bug?

doegox commented 10 months ago

So it won't cause issues later? Only one time bug?

Well I don't know what you are doing with the git version string in your app, but every time there will be a release from a release tag, the version string will just be the tag name...

Foxushka commented 10 months ago

We parse commit from last release (or action as fallback) and if it doesn't starts with reported version from chameleon we preform update

doegox commented 10 months ago

We parse commit from last release (or action as fallback) and if it doesn't starts with reported version from chameleon we preform update

when firmware git_version returns only a tag and no commit (e.g. on a release tag), you can get the corresponding hash with an API query, e.g.

wget -q -O - "https://api.github.com/repos/doegox/ChameleonUltra/tags"|jq '.[] | select(.name == "v2.0.0") | .commit | .sha'
"4747d3884d21e0df8549e3029a920ea390e0b00a"