├── .gitmodules ├── .gitignore ├── LICENSE ├── src ├── jc_cap │ ├── jc_cap_import.hpp │ ├── jc_cap_applet.hpp │ ├── jc_cap_reference_location.hpp │ ├── jc_cap_directory.hpp │ ├── jc_cap_header.hpp │ ├── jc_cap_static_field.hpp │ ├── jc_cap_export.hpp │ ├── jc_cap_method.hpp │ ├── jc_cap_cp.hpp │ └── jc_cap_descriptor.hpp ├── jc_types │ ├── jc_array_type.hpp │ ├── jc_object.cpp │ ├── jc_object.hpp │ ├── jc_field.hpp │ ├── jref_t.hpp │ ├── jc_instance.hpp │ ├── jref_t.cpp │ └── jc_array.hpp ├── jc_handlers │ ├── package.hpp │ ├── jc_component.hpp │ ├── jc_import.hpp │ ├── package.cpp │ ├── jc_method.hpp │ ├── jc_static.hpp │ ├── jc_export.hpp │ ├── jc_import.cpp │ ├── jc_export.cpp │ ├── jc_cap.hpp │ ├── jc_method.cpp │ ├── jc_static.cpp │ ├── jc_class.hpp │ └── jc_cp.hpp ├── debug.hpp ├── jc_config.h ├── main.cpp ├── exceptions.hpp ├── interpretor.hpp ├── context.hpp ├── jc_bytecodes │ ├── bc_others.cpp │ ├── bc_exceptions.cpp │ └── bc_return.cpp ├── jcvm_types │ ├── list.hpp │ ├── pc_t.hpp │ └── jcvmarray.hpp ├── types.hpp ├── context.cpp ├── heap.hpp ├── frame.hpp ├── jc_utils.hpp ├── heap.cpp ├── main_pc.cpp ├── frame.cpp └── stack.hpp ├── stm32f401xe.ld └── README.md /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "os"] 2 | path = os 3 | url = https://github.com/choupi-project/choupi-os 4 | [submodule "javacard-sdk/rommask"] 5 | path = javacard-sdk/rommask 6 | url = https://github.com/choupi-project/rommask 7 | [submodule "javacard-sdk/javacard-api"] 8 | path = javacard-sdk/javacard-api 9 | url = https://github.com/choupi-project/javacard-api 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Executables 18 | *.exe 19 | *.out 20 | *.app 21 | *.i*86 22 | *.x86_64 23 | *.hex 24 | 25 | # Debug files 26 | *.dSYM/ 27 | 28 | # Gcov file 29 | *.gcno 30 | *.gcda 31 | 32 | CMakeCache.txt 33 | CMakeFiles 34 | CMakeScripts 35 | Testing 36 | Makefile 37 | cmake_install.cmake 38 | install_manifest.txt 39 | compile_commands.json 40 | CTestTestfile.cmake 41 | build/ 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_import.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_IMPORT_HPP 29 | #define _JC_CAP_IMPORT_HPP 30 | 31 | #include "../types.hpp" 32 | #include "jc_cap_header.hpp" 33 | 34 | namespace jcvm { 35 | 36 | struct __attribute__((__packed__)) jc_cap_import_component { 37 | uint8_t tag; /* Component tag: COMPONENT_Import (4) */ 38 | uint16_t size; /* Component size */ 39 | uint8_t count; /* Number of items in the packages table */ 40 | uint8_t /* struct jc_cap_package_info */ 41 | imported_packages[/* count */]; /* Imported packages */ 42 | }; 43 | 44 | } // namespace jcvm 45 | 46 | #endif /* _JC_CAP_IMPORT_HPP */ 47 | -------------------------------------------------------------------------------- /src/jc_types/jc_array_type.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_ARRAY_TYPE_HPP 29 | #define _JC_ARRAY_TYPE_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../types.hpp" 33 | 34 | namespace jcvm { 35 | 36 | enum jc_array_type : uint8_t { 37 | // JAVA_ARRAY_UNINITIALIZED = 0x00, 38 | 39 | // JAVA_ARRAY_NOT_ARRAY = 0xFF, 40 | 41 | JAVA_ARRAY_T_BOOLEAN = 0x10, 42 | JAVA_ARRAY_T_BYTE = 0x11, 43 | JAVA_ARRAY_T_SHORT = 0x12, 44 | 45 | #ifdef JCVM_INT_SUPPORTED 46 | JAVA_ARRAY_T_INT = 0x13, 47 | #endif /* JCVM_INT_SUPPORTED */ 48 | 49 | JAVA_ARRAY_T_REFERENCE = 0x14, 50 | }; 51 | 52 | } // namespace jcvm 53 | #endif /* _JC_ARRAY_TYPE_HPP */ 54 | -------------------------------------------------------------------------------- /src/jc_handlers/package.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _PACKAGE_HPP 29 | #define _PACKAGE_HPP 30 | 31 | #include "../types.hpp" 32 | #include "jc_cap.hpp" 33 | 34 | namespace jcvm { 35 | class Package { 36 | private: 37 | jpackage_ID_t ID; 38 | 39 | public: 40 | /// Default constructor. 41 | Package(jpackage_ID_t packageID) noexcept; 42 | /// Equality operator. 43 | bool operator==(const Package &package) const; 44 | /// Inequality operator. 45 | bool operator!=(const Package &package) const; 46 | /// Get Package ID 47 | jpackage_ID_t getPackageID() const noexcept; 48 | /// Get CAP File 49 | JC_Cap getCap() const; 50 | }; 51 | 52 | } // namespace jcvm 53 | 54 | #endif /* _PACKAGE_HPP */ 55 | -------------------------------------------------------------------------------- /src/debug.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef __DEBUG_HPP_ 29 | #define __DEBUG_HPP_ 30 | 31 | #ifdef DEBUG 32 | #include 33 | #endif /* DEBUG */ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | // Trace function 40 | #ifdef DEBUG 41 | #define TRACE_JCVM_DEBUG(fmt, ...) printf("[-] " fmt "\r\n", ##__VA_ARGS__) 42 | #define TRACE_JCVM_ERR(fmt, ...) printf("[!] " fmt "\r\n", ##__VA_ARGS__) 43 | #else 44 | #define TRACE_JCVM_DEBUG(fmt, ...) ; 45 | #define TRACE_JCVM_ERR(fmt, ...) ; 46 | #endif /* DEBUG */ 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #ifdef DEBUG 53 | #pragma message "CHOUPI Debug mode enable" 54 | #endif /* DEBUG */ 55 | 56 | #endif /* __DEBUG_HPP_ */ 57 | -------------------------------------------------------------------------------- /src/jc_types/jc_object.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jc_object.hpp" 29 | 30 | namespace jcvm { 31 | 32 | /** 33 | * Gets the persistant state of the current object 34 | * 35 | * @return true if current instance is persistant 36 | */ 37 | bool JC_Object::isPersistent(void) const noexcept { 38 | return this->is_persistent; 39 | } 40 | 41 | /** 42 | * sets the persistant state of the current object 43 | * 44 | * @param[persistant] new persistant state. 45 | */ 46 | void JC_Object::setPersistent(const bool persistant) noexcept { 47 | this->is_persistent = persistant; 48 | } 49 | 50 | /* 51 | * Get heap owner. 52 | * 53 | * @return heap owner. 54 | */ 55 | Heap &JC_Object::getOwner() noexcept { return this->owner; } 56 | 57 | } // namespace jcvm 58 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_component.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_COMPONENT_HPP 29 | #define _JC_COMPONENT_HPP 30 | 31 | #include "../types.hpp" 32 | #include "package.hpp" 33 | 34 | namespace jcvm { 35 | 36 | class Component_Handler { 37 | protected: 38 | Package package; 39 | 40 | public: 41 | /// Default constructor 42 | Component_Handler(Package package) noexcept : package(package){}; 43 | 44 | /** 45 | * Set current Package 46 | * 47 | * @param[package] new package value 48 | */ 49 | void setPackage(Package package) noexcept { this->package = package; } 50 | 51 | /** 52 | * Get current Package 53 | * 54 | * @param[package] new package value 55 | */ 56 | Package &getPackage() noexcept { return this->package; } 57 | }; 58 | 59 | } // namespace jcvm 60 | 61 | #endif /* _JC_COMPONENT_HPP */ 62 | -------------------------------------------------------------------------------- /src/jc_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JCVM_CONFIG_H 29 | #define _JCVM_CONFIG_H 30 | 31 | #define JCVM_STACK_SIZE (uint16_t)(1024 >> 2) // 2-Bytes 32 | #define JCVM_MAX_HEAP_SIZE (uint16_t)256 // bytes 33 | /// NOTE: This size must be < to 0x7FFE. A max size more than 0x7FFE will occur 34 | /// several bugs. 35 | #define JCVM_MAX_APPLETS (uint16_t)40 // applets (max 255) 36 | #define JCVM_MAX_PACKAGES (uint8_t)64 // packages (max 255) 37 | 38 | #define JCRE_CLEAN_STACK 39 | #define JCVM_INT_SUPPORTED 40 | #define JCRE_STACK_OVERFLOW_PROTECTION 41 | #define JCVM_SECURE_HEAP_ACCESS 42 | #define JCVM_DYNAMIC_CHECKS_CAP 43 | #define JCVM_FIREWALL_CHECKS 44 | #define JCVM_ARRAY_SIZE_CHECK 45 | 46 | #define NVM_LITTLE_ENDIAN 47 | 48 | #undef JCRE_SWITCH_PROTECTION // TODO: To be tested and implemented 49 | #undef JCVM_TYPED_HEAP // TODO: not yet implemented 50 | #undef JCVM_TYPED_STACK // TODO: not yet implemented 51 | 52 | #endif /* _JCVM_CONFIG_H */ 53 | -------------------------------------------------------------------------------- /src/jc_types/jc_object.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_OBJECT_HPP 29 | #define _JC_OBJECT_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../types.hpp" 33 | 34 | namespace jcvm { 35 | 36 | class Heap; // fast forward declation; 37 | 38 | class JC_Object { 39 | private: 40 | /// Heap owner 41 | Heap &owner; 42 | /// Is a persistent (aka in flash memory) object? 43 | bool is_persistent; 44 | /// Is a static (aka in flash memory) object? 45 | bool is_static; 46 | 47 | public: 48 | /// Default constructor 49 | JC_Object(Heap &owner, const bool isPersistent) noexcept 50 | : owner(owner), is_persistent(isPersistent){}; 51 | 52 | /// Gets the persistant state of the current object 53 | bool isPersistent(void) const noexcept; 54 | /// Sets the persistant state of the current object 55 | void setPersistent(const bool persistant) noexcept; 56 | 57 | /// Get heap owner. 58 | Heap &getOwner() noexcept; 59 | }; 60 | 61 | } // namespace jcvm 62 | #endif /* _JC_OBJECT_HPP */ 63 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_import.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_IMPORT_HPP 29 | #define _JC_IMPORT_HPP 30 | 31 | #include "../jc_config.h" 32 | 33 | #include "../jc_cap/jc_cap_header.hpp" 34 | #include "../jcvm_types/jcvmarray.hpp" 35 | #include "../types.hpp" 36 | #include "jc_component.hpp" 37 | 38 | namespace jcvm { 39 | 40 | class Import_Handler : public Component_Handler { 41 | public: 42 | /// Default constructor 43 | Import_Handler(Package package) noexcept : Component_Handler(package){}; 44 | 45 | /// Get import package AID from index. 46 | const jc_cap_package_info *getPackageAID(const uint8_t index) 47 | #if !defined(JCVM_ARRAY_SIZE_CHECK) 48 | noexcept 49 | #endif 50 | ; 51 | 52 | /// Get the package index in the flash. 53 | const jpackage_ID_t getPackageIndex(const jc_cap_package_info *pinfo); 54 | 55 | /// Get the package index in the flash from import component offset. 56 | const jpackage_ID_t getPackageIndexFromOffset(const uint8_t offset); 57 | }; 58 | 59 | } // namespace jcvm 60 | 61 | #endif /* _JC_IMPORT_HPP */ 62 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "debug.hpp" 29 | #include "interpretor.hpp" 30 | #include "jc_config.h" 31 | #include "types.hpp" 32 | 33 | #include "jc_handlers/flashmemory.hpp" 34 | 35 | #ifdef PC_VERSION 36 | extern int main_pc(int argc, char *argv[]); 37 | #else 38 | extern int main_arm(void); 39 | #endif /* PC_VERSION */ 40 | 41 | int main 42 | #ifdef PC_VERSION 43 | (int argc, char *argv[]) 44 | #else 45 | () 46 | #endif /* PC_VERSION */ 47 | { 48 | #ifdef PC_VERSION 49 | return main_pc(argc, argv); 50 | #else 51 | return main_arm(); 52 | #endif /* PC_VERSION */ 53 | } 54 | 55 | #ifdef __cplusplus 56 | extern "C" { 57 | #endif 58 | 59 | void runtime(uint8_t id_package, uint8_t id_class, uint8_t id_method) { 60 | TRACE_JCVM_DEBUG("Starting JCVM"); 61 | 62 | jcvm::japplet_ID_t id_applet = 0; 63 | 64 | // TODO: is a static method? 65 | jcvm::Interpretor interpretor(id_applet, 66 | static_cast(id_package), 67 | id_class, id_method, true); 68 | interpretor.run(); 69 | } 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | -------------------------------------------------------------------------------- /src/jc_handlers/package.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "package.hpp" 29 | #include "../jc_utils.hpp" 30 | #include "../jcvm_types/jcvmarray.hpp" 31 | #include "flashmemory.hpp" 32 | 33 | namespace jcvm { 34 | 35 | /** 36 | * Default constructor. 37 | * 38 | * @param[packageID] package ID 39 | */ 40 | Package::Package(const jpackage_ID_t packageID) noexcept : ID(packageID) {} 41 | 42 | /** 43 | * Equality operator 44 | * 45 | * @param[package] 46 | * 47 | * @return True if packages are not equal. 48 | */ 49 | bool Package::operator==(const Package &package) const { 50 | return (this->ID == package.ID); 51 | } 52 | 53 | /** 54 | * Inequality operator 55 | * 56 | * @param[package] 57 | * 58 | * @return True if packages are equal. 59 | */ 60 | bool Package::operator!=(const Package &package) const { 61 | return (this->ID != package.ID); 62 | } 63 | 64 | /** 65 | * Get Package ID 66 | */ 67 | jpackage_ID_t Package::getPackageID() const noexcept { return this->ID; } 68 | 69 | /** 70 | * Get CAP File 71 | * 72 | * @return Package CAP file. 73 | */ 74 | JC_Cap Package::getCap() const { return FlashMemory_Handler::getCap(this->ID); } 75 | 76 | } // namespace jcvm 77 | -------------------------------------------------------------------------------- /src/exceptions.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _EXCEPTIONS_HPP 29 | #define _EXCEPTIONS_HPP 30 | 31 | #include "jc_config.h" 32 | #include "types.hpp" 33 | 34 | namespace jcvm { 35 | 36 | enum Exceptions { 37 | NotYetImplemented, 38 | 39 | StackUnderflowException, 40 | StackOverflowException, 41 | // { CardExceptions 42 | CardException, 43 | UserException, 44 | // } 45 | // { IOExceptions 46 | IOException, 47 | RemoteException, 48 | // } 49 | // { RuntimeExceptions 50 | RuntimeException, 51 | ArithmeticException, 52 | ArrayStoreException, 53 | // {{ CardRuntimeExceptions 54 | CardRuntimeException, 55 | APDUException, 56 | Bio1NException, 57 | BioException, 58 | CryptoException, 59 | ExternalException, 60 | ISOException, 61 | PINException, 62 | StringException, 63 | ServiceException, 64 | SystemException, 65 | TLVException, 66 | TransactionException, 67 | UtilException, 68 | /// }} 69 | ClassCastException, 70 | // {{ IndexOutOfBoundsExceptions 71 | IndexOutOfBoundsException, 72 | ArrayIndexOutOfBoundsException, 73 | // }} 74 | NegativeArraySizeException, 75 | NullPointerException, 76 | SecurityException, 77 | // } 78 | FullMemoryException 79 | }; 80 | 81 | } // namespace jcvm 82 | #endif /* _EXCEPTIONS_HPP */ 83 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_method.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_METHOD_HPP 29 | #define _JC_METHOD_HPP 30 | 31 | #include "../context.hpp" 32 | #include "../jc_cap/jc_cap_method.hpp" 33 | #include "../jc_utils.hpp" 34 | #include "../types.hpp" 35 | #include "jc_cap.hpp" 36 | #include "jc_component.hpp" 37 | 38 | namespace jcvm { 39 | 40 | class Method_Handler : public Component_Handler { 41 | private: 42 | Context &context; 43 | 44 | /// Get method from offset. 45 | const uint8_t *getMethodFromOffset(const uint16_t method_offset) 46 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 47 | noexcept 48 | #endif 49 | ; 50 | 51 | void callMethod(const uint8_t *const method_to_call, 52 | const jbool_t isStaticMethod = FALSE) 53 | #if !defined(JCVM_DYNAMIC_CHECKS_CAP) && !defined(JCVM_FIREWALL_CHECKS) 54 | noexcept 55 | #endif 56 | ; 57 | 58 | public: 59 | /// Default constructor 60 | Method_Handler(Context &context) noexcept 61 | : Component_Handler(context.getCurrentPackage()), context(context){}; 62 | 63 | /// Call a virtual method 64 | void callVirtualMethod(const uint16_t method_offset); 65 | 66 | /// Call a static method 67 | void callStaticMethod(const uint16_t method_offset); 68 | }; 69 | 70 | } // namespace jcvm 71 | #endif /* _JC_METHOD_HPP */ 72 | -------------------------------------------------------------------------------- /src/interpretor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_INTERPRETOR_HPP 29 | #define _JC_INTERPRETOR_HPP 30 | 31 | #include "context.hpp" 32 | #include "exceptions.hpp" 33 | #include "jc_config.h" 34 | #include "jcvm_types/list.hpp" 35 | #include "types.hpp" 36 | 37 | namespace jcvm { 38 | 39 | class Interpretor { 40 | public: 41 | /// Default constructor. 42 | Interpretor( 43 | const japplet_ID_t appletID, const jpackage_ID_t selectedPackageID, 44 | const uint8_t selectedClass, const uint8_t method, 45 | bool isStaticMethod) noexcept(noexcept(std::declval &>() 46 | .push_back(std::declval< 47 | Context &>()))); 48 | 49 | /// Run the Java Card Interpretor. 50 | void run() noexcept; // All exceptions must be handling there. 51 | 52 | /// Get the current context 53 | Context &getCurrentContext() noexcept( 54 | noexcept(std::declval &>().at(std::declval()))); 55 | 56 | void startJCVMException(Exceptions); 57 | 58 | private: 59 | /// List of Java Card contexts. 60 | List contexts; 61 | /// Class and method where the interpretor start. 62 | uint8_t startingClass, startingMethod; 63 | bool isStaticStatingMethod; 64 | }; 65 | 66 | } // namespace jcvm 67 | 68 | #endif /* _JC_INTERPRETOR_HPP */ 69 | -------------------------------------------------------------------------------- /src/context.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _CONTEXT_HPP 29 | #define _CONTEXT_HPP 30 | 31 | #include "heap.hpp" 32 | #include "jc_config.h" 33 | #include "jc_handlers/package.hpp" 34 | #include "jcvm_types/list.hpp" 35 | #include "stack.hpp" 36 | #include "types.hpp" 37 | 38 | namespace jcvm { 39 | 40 | class Context { 41 | private: 42 | /// Applet ID. 43 | japplet_ID_t applet_ID; 44 | /// Current Java Card stack. 45 | Stack stack; 46 | /// Linked-list where the executed Packages ID is stored. The Head of the 47 | /// linked-list is the current executed package ID. 48 | List packagesID; 49 | /// Context's heap 50 | Heap heap; 51 | 52 | public: 53 | /// Default constructor 54 | Context(const uint8_t appletID, const jpackage_ID_t packageID) noexcept; 55 | /// Get the context ID. 56 | jpackage_ID_t getCurrentPackageID() noexcept; 57 | /// Get applet ID 58 | japplet_ID_t getAppletID() noexcept; 59 | /// Get context Java Card stack. 60 | Stack &getStack() noexcept; 61 | /// Get context heap. 62 | Heap &getHeap() noexcept; 63 | /// Get current current package. 64 | Package getCurrentPackage(); 65 | /// Shift context package ID 66 | void changePackageID(const uint8_t packageID) noexcept; 67 | /// Back to the previous package ID. 68 | void backToPreviousPackageID() noexcept; 69 | }; 70 | 71 | } // namespace jcvm 72 | 73 | #endif /* _CONTEXT_HPP */ 74 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_static.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_STATIC_HPP 29 | #define _JC_STATIC_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_types/jref_t.hpp" 33 | #include "../types.hpp" 34 | #include "jc_component.hpp" 35 | 36 | namespace jcvm { 37 | 38 | class Heap; // Forward declaration of Heap 39 | 40 | class Static_Handler : public Component_Handler { 41 | public: 42 | /// Default constructor 43 | Static_Handler(Package package) noexcept : Component_Handler(package){}; 44 | 45 | /// Read static byte value. 46 | jbyte_t getPersistentByte(const uint16_t index) const; 47 | /// Read static short value. 48 | jshort_t getPersistentShort(const uint16_t index) const; 49 | #ifdef JCVM_INT_SUPPORTED 50 | /// Read static integer value. 51 | jint_t getPersistentInt(const uint16_t index) const; 52 | #endif /* JCVM_INT_SUPPORTED */ 53 | /// Read static serialized instance or array. 54 | jref_t getPersistentRef(const uint16_t index, Heap &heap) const; 55 | 56 | /// Set static byte value. 57 | void setPersistentByte(const uint16_t index, const jbyte_t value); 58 | /// Set static short value. 59 | void setPersistentShort(const uint16_t index, const jshort_t value); 60 | #ifdef JCVM_INT_SUPPORTED 61 | /// Set static integer value. 62 | void setPersistentInt(const uint16_t index, const jint_t value); 63 | #endif /* JCVM_INT_SUPPORTED */ 64 | }; 65 | 66 | } // namespace jcvm 67 | 68 | #endif /* _JC_STATIC_HPP */ 69 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_applet.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_APPLET_HPP 29 | #define _JC_CAP_APPLET_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_app { 38 | uint8_t AID_length; /* Applet AID length = [5,16] */ 39 | // { 40 | // uint8_t AID [/* AID_length */]; /* Applet AID */ 41 | // uint16_t install_method_offset; /* Applet install method offset in the 42 | // Method 43 | // component */ 44 | // } 45 | uint8_t data[]; 46 | 47 | const JCVMArray AID() const noexcept { 48 | return JCVMArray(NTOHS(AID_length), data); 49 | } 50 | 51 | uint16_t install_method_offset() const noexcept { 52 | return BYTES_TO_SHORT(this->data[AID_length], this->data[AID_length + 1]); 53 | } 54 | }; 55 | 56 | struct __attribute__((__packed__)) jc_cap_applet_component { 57 | uint8_t tag; /* Component tag: COMPONENT_Applet (3) */ 58 | uint16_t size; /* Component size */ 59 | uint8_t count; /* Number of applet defined in this package */ 60 | jc_cap_app applets[/* count */]; /* Applet defined in this package */ 61 | 62 | const JCVMArray applet() const noexcept { 63 | return JCVMArray(NTOHS(count), applets); 64 | } 65 | }; 66 | 67 | } // namespace jcvm 68 | 69 | #endif /* _JC_CAP_APPLET_HPP */ 70 | -------------------------------------------------------------------------------- /src/jc_types/jc_field.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_FIELD_HPP 29 | #define _JC_FIELD_HPP 30 | 31 | #include "../types.hpp" 32 | 33 | namespace jcvm { 34 | 35 | enum FieldType : uint8_t { 36 | FIELD_TYPE_BYTE = (uint8_t)0, 37 | FIELD_TYPE_BOOLEAN = (uint8_t)1, 38 | FIELD_TYPE_SHORT = (uint8_t)2, 39 | #ifdef JCVM_INT_SUPPORTED 40 | FIELD_TYPE_INT = (uint8_t)3, 41 | #endif /* JCVM_INT_SUPPORTED */ 42 | FIELD_TYPE_OBJECT = (uint8_t)4, 43 | 44 | FIELD_TYPE_ARRAY_BYTE = (uint8_t)((1 << 7) | FIELD_TYPE_BYTE), 45 | FIELD_TYPE_ARRAY_BOOLEAN = (uint8_t)((1 << 7) | FIELD_TYPE_BOOLEAN), 46 | FIELD_TYPE_ARRAY_SHORT = (uint8_t)((1 << 7) | FIELD_TYPE_SHORT), 47 | #ifdef JCVM_INT_SUPPORTED 48 | FIELD_TYPE_ARRAY_INT = (uint8_t)((1 << 7) | FIELD_TYPE_INT), 49 | #endif /* JCVM_INT_SUPPORTED */ 50 | FIELD_TYPE_ARRAY_OBJECT = (uint8_t)((1 << 7) | FIELD_TYPE_OBJECT), 51 | 52 | FIELD_TYPE_TRANSIENT_ARRAY_BYTE = (uint8_t)((1 << 6) | FIELD_TYPE_ARRAY_BYTE), 53 | FIELD_TYPE_TRANSIENT_ARRAY_BOOLEAN = 54 | (uint8_t)((1 << 6) | FIELD_TYPE_ARRAY_BOOLEAN), 55 | FIELD_TYPE_TRANSIENT_ARRAY_SHORT = 56 | (uint8_t)((1 << 6) | FIELD_TYPE_ARRAY_SHORT), 57 | #ifdef JCVM_INT_SUPPORTED 58 | FIELD_TYPE_TRANSIENT_ARRAY_INT = (uint8_t)((1 << 6) | FIELD_TYPE_ARRAY_INT), 59 | #endif /* JCVM_INT_SUPPORTED */ 60 | FIELD_TYPE_TRANSIENT_ARRAY_OBJECT = 61 | (uint8_t)((1 << 6) | FIELD_TYPE_ARRAY_OBJECT), 62 | 63 | FIELD_TYPE_UNINITIALIZED = (uint8_t)(-1), 64 | 65 | }; // namespace jcvm 66 | 67 | struct jc_field_t { 68 | FieldType type; 69 | jword_t value; 70 | }; 71 | 72 | } // namespace jcvm 73 | 74 | #endif /* _JC_FIELD_HPP */ 75 | -------------------------------------------------------------------------------- /src/jc_bytecodes/bc_others.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "../debug.hpp" 29 | #include "bytecodes.hpp" 30 | 31 | namespace jcvm { 32 | 33 | extern void callJCNativeMethod(Context &, jshort_t); 34 | 35 | /** 36 | * Do nothing 37 | * 38 | * Format: 39 | * nop 40 | * 41 | * Forms: 42 | * nop = 00 (0x00) 43 | * 44 | * Stack: 45 | * No change. 46 | * 47 | * Description: 48 | * 49 | * Do Nothing. 50 | */ 51 | void Bytecodes::bc_nop() { 52 | TRACE_JCVM_DEBUG("NOP"); 53 | 54 | return; 55 | } 56 | 57 | /** 58 | * Call implementation depend 1 instruction 59 | * 60 | * Format: 61 | * impdep1 62 | * 63 | * Forms: 64 | * impedp1 = 254 (0xFE) 65 | * 66 | * Stack: 67 | * ..., index -> ..., [result] 68 | * 69 | * Description: 70 | * 71 | * Call native method. 72 | */ 73 | void Bytecodes::bc_impdep1() { 74 | jshort_t index; 75 | Stack &stack = this->context.getStack(); 76 | 77 | TRACE_JCVM_DEBUG("IMPDEP1"); 78 | 79 | index = stack.pop_Short(); 80 | callJCNativeMethod(this->context, index); 81 | 82 | return; 83 | } 84 | 85 | /** 86 | * Call implementation depend 2 instruction 87 | * 88 | * Format: 89 | * impdep1 90 | * 91 | * Forms: 92 | * impedp2 = 255 (0xFF) 93 | * 94 | * Stack: 95 | * ..., index -> ..., [result] 96 | * 97 | * Description: 98 | * 99 | * Call native method. 100 | */ 101 | void Bytecodes::bc_impdep2() { 102 | // jshort_t index; 103 | // Stack &stack = this->context.getStack(); 104 | 105 | TRACE_JCVM_DEBUG("IMPDEP2"); 106 | 107 | throw Exceptions::NotYetImplemented; 108 | 109 | return; 110 | } 111 | 112 | } // namespace jcvm 113 | -------------------------------------------------------------------------------- /src/jcvm_types/list.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _LIST_HPP 29 | #define _LIST_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../types.hpp" 33 | #include 34 | #include 35 | 36 | #ifdef JCVM_ARRAY_SIZE_CHECK 37 | #include "../exceptions.hpp" 38 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 39 | 40 | namespace jcvm { 41 | template class List : public std::list { 42 | 43 | public: 44 | /// Access specified element with bounds checking. 45 | constexpr T &at(uint16_t index) 46 | #ifndef JCVM_ARRAY_SIZE_CHECK 47 | noexcept 48 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 49 | { 50 | typename std::list::iterator lit = this->begin(); 51 | 52 | #ifdef JCVM_ARRAY_SIZE_CHECK 53 | 54 | if (index >= this->size()) { 55 | throw Exceptions::IndexOutOfBoundsException; 56 | } 57 | 58 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 59 | 60 | // list iterator is a bidirectional iterator without random access. 61 | for (uint16_t foo = 0; foo < index; ++foo) { 62 | lit++; 63 | } 64 | 65 | return *lit; 66 | } 67 | 68 | constexpr T &at(uint16_t index) const 69 | #ifndef JCVM_ARRAY_SIZE_CHECK 70 | noexcept 71 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 72 | { 73 | typename std::list::const_iterator lit = this->cbegin(); 74 | 75 | #ifdef JCVM_ARRAY_SIZE_CHECK 76 | 77 | if (index >= this->size()) { 78 | throw Exceptions::IndexOutOfBoundsException; 79 | } 80 | 81 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 82 | 83 | // list iterator is a bidirectional iterator without random access. 84 | for (uint16_t foo = 0; foo < index; ++foo) { 85 | lit++; 86 | } 87 | 88 | return *lit; 89 | } 90 | }; 91 | 92 | } // namespace jcvm 93 | 94 | #endif /* _LIST_HPP */ 95 | -------------------------------------------------------------------------------- /src/types.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _TYPES_HPP 29 | #define _TYPES_HPP 30 | 31 | #include "jc_config.h" 32 | 33 | /* 34 | * XXX: For Java Card language: 35 | * - A byte is a signed 8-bit type. 36 | * - A short is a signed 16-bit type. 37 | * - An int is a signed 32-bit type. 38 | * - The reference type is not define: implementation dependent. 39 | * - The returnadress type is a Numerical type (but without arithmetic). 40 | */ 41 | #include 42 | 43 | namespace jcvm { 44 | 45 | /// a Java Card byte type 46 | typedef int8_t jbyte_t; 47 | /// a Java Card short type 48 | typedef int16_t jshort_t; 49 | /// a Java Card generic word type 50 | typedef jshort_t jword_t; 51 | #ifdef JCVM_INT_SUPPORTED 52 | /// a Java Card int type 53 | typedef int32_t jint_t; 54 | #endif /* JCVM_INT_SUPPORTED */ 55 | 56 | /// a Java Card Boolean type 57 | enum jbool_t : uint8_t { 58 | FALSE = static_cast(0), 59 | TRUE = static_cast(1), 60 | }; 61 | 62 | inline jbool_t byte2bool(const jbyte_t value) noexcept { 63 | switch (value) { 64 | case FALSE: 65 | return FALSE; 66 | 67 | case TRUE: 68 | default: 69 | return TRUE; 70 | } 71 | }; 72 | 73 | /// A Java Card Return address 74 | typedef uint16_t jreturnaddress_t; 75 | 76 | /// The constant pool component 77 | typedef uint16_t jc_cp_offset_t; 78 | 79 | /// Java Card package ID type 80 | typedef uint8_t jpackage_ID_t; 81 | 82 | /// Java Card applet ID type 83 | typedef uint8_t japplet_ID_t; 84 | 85 | /// Java Card class index type 86 | typedef uint16_t jclass_index_t; 87 | 88 | #define JTYPE_SHORT (uint8_t)0x0 89 | #define JTYPE_INT (uint8_t)0x7 // 0b0111 90 | #define JTYPE_INT_LOW_PART (uint8_t)0x5 // 0b0101 91 | #define JTYPE_INT_HIGH_PART (uint8_t)0x6 // 0b0110 92 | #define JTYPE_OBJECT (uint8_t)0x8 // 0b1000 93 | 94 | } // namespace jcvm 95 | 96 | #endif /* _TYPES_HPP */ 97 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_reference_location.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_REFERENCE_LOCATION_HPP 29 | #define _JC_CAP_REFERENCE_LOCATION_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_utils.hpp" 33 | #include "../jcvm_types/jcvmarray.hpp" 34 | #include "../types.hpp" 35 | 36 | namespace jcvm { 37 | 38 | struct __attribute__((__packed__)) jc_cap_reference_location_component { 39 | /// Component tag: COMPONENT_ReferenceLocation (9) 40 | uint8_t tag; 41 | /// Component size 42 | uint16_t size; 43 | uint8_t data[/* size */]; 44 | // { 45 | // /// Number of elements in the offsets_to_byte2_indices array 46 | // uint16_t byte_index_count; 47 | // /// 1-byte token offset in the Method component 48 | // uint8_t offsets_to_byte_indices [/* byte_index_count */]; 49 | // /// Number of elements in the offsets_to_byte2_indices array 50 | // uint16_t byte2_index_count; 51 | // /// 2-byte token offset in the Method component 52 | // uint8_t offsets_to_byte2_indices [/* byte2_index_count */]; 53 | // } 54 | 55 | uint16_t byte_index_count() const noexcept { 56 | return BYTES_TO_SHORT(data[0], data[1]); 57 | } 58 | 59 | JCVMArray offsets_to_byte_indices() const noexcept { 60 | return JCVMArray(byte_index_count(), 61 | (data + sizeof(uint16_t))); 62 | } 63 | 64 | uint16_t byte2_index_count() const noexcept { 65 | return BYTES_TO_SHORT(data[byte_index_count() + sizeof(uint16_t)], 66 | data[byte_index_count() + sizeof(uint16_t) + 1]); 67 | } 68 | 69 | const JCVMArray offsets_to_byte2_indices() const noexcept { 70 | return JCVMArray( 71 | byte2_index_count(), 72 | (data + byte_index_count() + 2 * sizeof(uint16_t))); 73 | } 74 | }; 75 | 76 | } // namespace jcvm 77 | 78 | #endif /* _JC_CAP_REFERENCE_LOCATION_HPP */ 79 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_export.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_EXPORT_HPP 29 | #define _JC_EXPORT_HPP 30 | 31 | #include "../jc_config.h" 32 | 33 | #include "../jc_cap/jc_cap_export.hpp" 34 | #include "../types.hpp" 35 | #include "jc_component.hpp" 36 | 37 | namespace jcvm { 38 | 39 | class Export_Handler : public Component_Handler { 40 | public: 41 | /// Default constructor 42 | Export_Handler(Package package) noexcept : Component_Handler(package){}; 43 | 44 | /// Get an exported class from a class offset 45 | const jc_cap_class_export_info & 46 | getExportedClass(const uint16_t class_export_offset) const 47 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 48 | noexcept 49 | #endif 50 | ; 51 | 52 | /// Get an exported class index on the class component 53 | const jclass_index_t 54 | getExportedClassOffset(const uint16_t class_export_offset) const 55 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 56 | noexcept 57 | #endif 58 | ; 59 | 60 | /// Get static field offset in the Static field component from static 61 | /// method offset in the Export component. 62 | uint16_t getExportedStaticFieldOffset(const uint16_t class_export_offset, 63 | const uint8_t static_field_offset) const 64 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 65 | noexcept 66 | #endif 67 | ; 68 | 69 | /// Get static method offset in the method component from static method offset 70 | /// in the Export component. 71 | uint16_t 72 | getExportedStaticMethodOffset(const uint16_t class_export_offset, 73 | const uint8_t static_method_offset) const 74 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 75 | noexcept 76 | #endif 77 | ; 78 | }; 79 | 80 | } // namespace jcvm 81 | 82 | #endif /* _JC_EXPORT_HPP */ 83 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_directory.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_DIRECTORY_HPP 29 | #define _JC_CAP_DIRECTORY_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_static_field_size_info { 38 | uint16_t image_size; /* Total number of bytes in the static fields */ 39 | uint16_t array_init_count; /* Number of arrays initialized */ 40 | uint16_t 41 | array_init_size; /* Number of bytes in all of the arrays initialized */ 42 | }; 43 | 44 | struct __attribute__((__packed__)) jc_cap_custom_component_info { 45 | uint8_t component_tag; /* Custom component tag = [128, 255] */ 46 | uint16_t size; /* Custom component size */ 47 | uint8_t AID_length; /* Package AID length = [5,16] */ 48 | uint8_t AID[/* AID_length */]; 49 | 50 | const JCVMArray aid() const noexcept { 51 | return JCVMArray(AID_length, AID); 52 | } 53 | }; 54 | 55 | struct __attribute__((__packed__)) jc_cap_directory_component { 56 | uint8_t tag; /* Component size: COMPONENT_Directory (2) */ 57 | uint16_t size; /* Component size */ 58 | uint16_t component_sizes[11]; /* Size of CAP file components */ 59 | jc_cap_static_field_size_info static_field_size; /* Static field size */ 60 | uint8_t import_count; /* Number of packages imported */ 61 | uint8_t applet_count; /* Number of applet defined in this package */ 62 | uint8_t custom_count; /* Number of entries in the custom_components table */ 63 | jc_cap_custom_component_info custom_components[/* custom_count */]; 64 | 65 | const JCVMArray customcomponents() const 66 | noexcept { 67 | return JCVMArray(custom_count, 68 | custom_components); 69 | } 70 | }; 71 | 72 | } // namespace jcvm 73 | 74 | #endif /* _JC_CAP_DIRECTORY_HPP */ 75 | -------------------------------------------------------------------------------- /src/jc_types/jref_t.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JREF_T_HPP 29 | #define _JREF_T_HPP 30 | 31 | #include "../exceptions.hpp" 32 | #include "../types.hpp" 33 | 34 | namespace jcvm { 35 | 36 | /// a Java Card reference 37 | struct jref_t { 38 | private: 39 | union _jref_t_type { 40 | struct { 41 | uint16_t isArray : 1; 42 | uint16_t offset : 15; 43 | } unpacked; 44 | uint16_t packed; 45 | 46 | _jref_t_type(const uint16_t value) noexcept { this->packed = value; }; 47 | 48 | } value; 49 | 50 | public: 51 | /// Default constructor. 52 | jref_t(uint16_t value = 0) noexcept; 53 | /// Move constructor. 54 | jref_t(const jref_t &) = default; 55 | /// Copy constructor. 56 | jref_t &operator=(const jref_t &); 57 | 58 | /// Get a compact version of this class. 59 | uint16_t compact() const noexcept; 60 | 61 | /// Is an array? 62 | bool isArray() const noexcept; 63 | /// Set as an array 64 | void setAsArray(const bool isArray) noexcept; 65 | // Is an instance? 66 | bool isInstance() const noexcept; 67 | /// Set as an instance 68 | void setAsInstance(const bool isInstance) noexcept; 69 | 70 | /// Get reference object in case of non persistent data. 71 | uint16_t getOffset() const noexcept; 72 | /// Set reference object. 73 | void setOffset(const uint16_t offset) noexcept; 74 | 75 | /// Is a Java NULL pointer. 76 | bool isNullPointer() const noexcept; 77 | 78 | /// Equality operator. 79 | bool operator==(const jref_t &) const noexcept; 80 | /// Inequality operator. 81 | bool operator!=(const jref_t &) const noexcept; 82 | /// Less than operator. 83 | bool operator<(const jref_t &) const noexcept; 84 | /// Less than or equality operator. 85 | bool operator<=(const jref_t &) const noexcept; 86 | /// Greater than operator. 87 | bool operator>(const jref_t &) const noexcept; 88 | /// Greater than or equality operator. 89 | bool operator>=(const jref_t &) const noexcept; 90 | 91 | }; // reference type 92 | 93 | } // namespace jcvm 94 | 95 | #endif /* _JREF_T_HPP */ 96 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_header.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_HEADER_HPP 29 | #define _JC_CAP_HEADER_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | #include 35 | 36 | namespace jcvm { 37 | 38 | struct __attribute__((__packed__)) jc_cap_package_info { 39 | uint8_t minor_version; /* Package minor version */ 40 | uint8_t major_version; /* Package major version */ 41 | uint8_t AID_length; /* Package AID Length */ 42 | uint8_t AID[/* AID_length */]; /* Package AID */ 43 | 44 | const JCVMArray aid() const noexcept { 45 | return JCVMArray(AID_length, AID); 46 | } 47 | 48 | jbool_t operator==(const jc_cap_package_info &package_info) const noexcept { 49 | if (AID_length != package_info.AID_length) { 50 | return FALSE; 51 | } 52 | 53 | if ((major_version != package_info.major_version) || 54 | (minor_version != package_info.minor_version)) { 55 | return FALSE; 56 | } 57 | 58 | if (memcmp(AID, package_info.AID, AID_length) == 0) { 59 | return TRUE; 60 | } 61 | 62 | return FALSE; 63 | } 64 | 65 | const uint32_t size() const noexcept { 66 | return sizeof(jc_cap_package_info) + 67 | this->AID_length * sizeof(this->AID[0]); 68 | } 69 | }; 70 | 71 | struct __attribute__((__packed__)) jc_cap_header_component { 72 | uint8_t tag; /* Component tag: COMPONENT_Header (1) */ 73 | uint16_t size; /* Component size */ 74 | uint32_t magic; /* CAP file magic number = 0xDECAFFED */ 75 | uint8_t minor_version; /* CAP File version */ 76 | uint8_t major_version; /* XXX: only the version 2.1 is implemented */ 77 | uint8_t flags; /* CAP File features used */ 78 | jc_cap_package_info package; /* Implemented package info */ 79 | }; 80 | 81 | #define JC_CAP_FLAG_ACC_INT 0x01 82 | #define JC_CAP_FLAG_ACC_EXPORT 0x02 83 | #define JC_CAP_FLAG_ACC_APPLET 0x04 84 | 85 | } // namespace jcvm 86 | 87 | #endif /* _JC_CAP_HEADER_HPP */ 88 | -------------------------------------------------------------------------------- /src/context.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "context.hpp" 29 | 30 | namespace jcvm { 31 | 32 | /** 33 | * Default constructor 34 | * 35 | * @param[packageID] Starting package ID. 36 | */ 37 | Context::Context(const japplet_ID_t appletID, 38 | const jpackage_ID_t packageID) noexcept 39 | : applet_ID(appletID), stack(), packagesID(), heap(appletID) { 40 | this->packagesID.push_front(packageID); 41 | } 42 | 43 | /** 44 | * Get current context ID. 45 | * 46 | * @return current context ID 47 | */ 48 | jpackage_ID_t Context::getCurrentPackageID() noexcept { 49 | return *(this->packagesID.cbegin()); 50 | } 51 | 52 | /** 53 | * Get applet class ID. 54 | * 55 | * @return current applet class ID 56 | */ 57 | jpackage_ID_t Context::getAppletID() noexcept { return this->applet_ID; } 58 | 59 | /** 60 | * Get context Java Card stack. 61 | * 62 | * @return context Java Card stack. 63 | */ 64 | Stack &Context::getStack() noexcept { return this->stack; } 65 | 66 | /** 67 | * Get context heap. 68 | * 69 | * @return context Java Card stack. 70 | */ 71 | Heap &Context::getHeap() noexcept { return this->heap; } 72 | 73 | /** 74 | * Get current package. 75 | * 76 | * @return current package. 77 | */ 78 | Package Context::getCurrentPackage() { 79 | return Package(this->getCurrentPackageID()); 80 | } 81 | 82 | /** 83 | * Shift the context package ID. This function is call when an invoke 84 | * instruction is invoked. There, the security context ID does not change but 85 | * the executed package changed. 86 | * 87 | * @param[packageID] new executed package ID. 88 | */ 89 | void Context::changePackageID(const jpackage_ID_t packageID) noexcept { 90 | this->packagesID.push_front(packageID); 91 | } 92 | 93 | /** 94 | * Shift the context package ID to the caller one. This function is call when 95 | * a return instruction is executed. There, the security context ID does not 96 | * change but the executed package changed. 97 | */ 98 | void Context::backToPreviousPackageID() noexcept { 99 | this->packagesID.pop_front(); 100 | } 101 | 102 | } // namespace jcvm 103 | -------------------------------------------------------------------------------- /src/heap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _HEAP_HPP 29 | #define _HEAP_HPP 30 | 31 | #include "exceptions.hpp" 32 | #include "jc_config.h" 33 | #include "jc_handlers/flashmemory.hpp" 34 | #include "jc_types/jc_array_type.hpp" 35 | #include "jc_types/jc_instance.hpp" 36 | #include "jc_types/jref_t.hpp" 37 | #include "jc_utils.hpp" 38 | #include "jcvm_types/list.hpp" 39 | #include "types.hpp" 40 | 41 | #include 42 | 43 | namespace jcvm { 44 | 45 | class JC_Array; // Forward declaration of JC_Array 46 | 47 | class Heap { 48 | private: 49 | /// 50 | const japplet_ID_t owner; 51 | 52 | /// List of array in the heap. 53 | List> arrays; 54 | /// List of instance in the heap. 55 | List> instances; 56 | 57 | /// Getting field reference from an instance reference. 58 | // jc_field_t &getFieldFromInstanceRef(jref_t objectref, uint16_t index); 59 | 60 | public: 61 | /// Default constructor. 62 | Heap(const japplet_ID_t owner) noexcept; 63 | 64 | /// Getting the applet ID owner 65 | japplet_ID_t getOwner() const; 66 | 67 | /// Adding new array in the transient heap. 68 | jref_t addArray(const uint16_t nb_entry, const jc_array_type type); 69 | /// Adding new reference array in the transient heap. 70 | jref_t addArray(const uint16_t nb_entry, const jc_array_type type, 71 | const jc_cp_offset_t array_reference_type); 72 | /// Adding an array in in the transient heap. 73 | jref_t addArray(JC_Array array); 74 | /// Adding new instance in the transient heap. 75 | jref_t addInstance(const jpackage_ID_t packageID, 76 | const jclass_index_t instantiated_class); 77 | /// Adding an instance in in the transient heap. 78 | jref_t addInstance(JC_Instance intance); 79 | 80 | /// Getting array from the transient heap. 81 | std::shared_ptr getArray(const jref_t objectref) 82 | #ifndef JCVM_SECURE_HEAP_ACCESS 83 | noexcept 84 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 85 | ; 86 | 87 | /// Getting instance from the transient heap. 88 | std::shared_ptr getInstance(const jref_t objectref) 89 | #ifndef JCVM_SECURE_HEAP_ACCESS 90 | noexcept 91 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 92 | ; 93 | }; 94 | 95 | } // namespace jcvm 96 | 97 | #endif /* _HEAP_HPP */ 98 | -------------------------------------------------------------------------------- /src/jcvm_types/pc_t.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _PC_T_HPP 29 | #define _PC_T_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_utils.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | class pc_t { 37 | private: 38 | const uint8_t *value; 39 | /** 40 | * Incrementing PC value 41 | */ 42 | void inc() noexcept { this->value += 1; } 43 | 44 | public: 45 | /** 46 | * Defaut constructor 47 | * 48 | * @param[value] initial PC value 49 | */ 50 | pc_t(const uint8_t *value) { this->value = value; } 51 | 52 | /** 53 | * Sets the new PC value 54 | * 55 | * @param[value] new PC value 56 | */ 57 | void setValue(pc_t pc) { this->value = pc.value; } 58 | 59 | /** 60 | * Sets the new PC value 61 | * 62 | * @param[value] new PC value 63 | */ 64 | void setValue(const uint8_t *value) { this->value = value; } 65 | 66 | /** 67 | * Returns the PC value. 68 | */ 69 | const uint8_t *getValue() const noexcept { return this->value; } 70 | 71 | /** 72 | * Gets next byte value and increment the PC value. 73 | */ 74 | jbyte_t getNextByte() noexcept { 75 | jbyte_t ret = (jbyte_t) * (this->value); 76 | this->inc(); 77 | return ret; 78 | } 79 | 80 | /** 81 | * Gets next 2-byte value and increment the PC value. 82 | */ 83 | jshort_t getNextShort() noexcept { 84 | jbyte_t msb = (jbyte_t) * (this->value); 85 | this->inc(); 86 | jbyte_t lsb = (jbyte_t) * (this->value); 87 | this->inc(); 88 | return BYTES_TO_SHORT(msb, lsb); 89 | } 90 | 91 | #ifdef JCVM_INT_SUPPORTED 92 | /** 93 | * Gets next 4-byte value and increment the PC value. 94 | */ 95 | jint_t getNextInt() noexcept { 96 | jbyte_t msb0 = (jbyte_t) * (this->value); 97 | this->inc(); 98 | jbyte_t lsb0 = (jbyte_t) * (this->value); 99 | this->inc(); 100 | jbyte_t msb1 = (jbyte_t) * (this->value); 101 | this->inc(); 102 | jbyte_t lsb1 = (jbyte_t) * (this->value); 103 | this->inc(); 104 | return BYTES_TO_INT(msb0, lsb0, msb1, lsb1); 105 | } 106 | #endif /* JCVM_INT_SUPPORTED */ 107 | 108 | /** 109 | * Update the PC value from an relative offset 110 | * 111 | * @param [offset] relative offset used to update the PC value 112 | */ 113 | void updateFromOffset(const jshort_t offset) { this->value += offset; } 114 | }; 115 | 116 | } // namespace jcvm 117 | 118 | #endif /* _PC_T_HPP */ 119 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_import.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jc_import.hpp" 29 | #include "../debug.hpp" 30 | #include "../jc_cap/jc_cap_import.hpp" 31 | #include "flashmemory.hpp" 32 | 33 | namespace jcvm { 34 | 35 | /* 36 | * Get import package AID from index. 37 | * 38 | * @param[index] package index 39 | * @return the AID of the package. 40 | */ 41 | const jc_cap_package_info *Import_Handler::getPackageAID(const uint8_t index) 42 | #if !defined(JCVM_ARRAY_SIZE_CHECK) 43 | noexcept 44 | #endif 45 | { 46 | const JC_Cap &cap = this->package.getCap(); 47 | const jc_cap_import_component *import = cap.getImport(); 48 | 49 | #ifdef JCVM_ARRAY_SIZE_CHECK 50 | 51 | if (import->count <= index) { 52 | 53 | TRACE_JCVM_DEBUG( 54 | "Imported package index (%u) > imported packages number (%u)", index, 55 | import->count); 56 | 57 | throw Exceptions::SecurityException; 58 | } 59 | 60 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 61 | 62 | uint16_t pos = 0; 63 | const jc_cap_package_info *package_info; 64 | 65 | for (uint8_t foo = 0; foo <= index; foo++) { 66 | package_info = reinterpret_cast( 67 | &import->imported_packages[pos]); 68 | pos += package_info->size(); 69 | } 70 | 71 | return package_info; 72 | } 73 | 74 | /* 75 | * Get the package index in the flash. 76 | * 77 | * @param[pinfo] package info which contains the package information to find. 78 | */ 79 | const jpackage_ID_t 80 | Import_Handler::getPackageIndex(const jc_cap_package_info *pinfo) { 81 | for (jpackage_ID_t index = 0; index < JCVM_MAX_PACKAGES; index++) { 82 | if (!FlashMemory_Handler::isPackageExist(index)) { 83 | continue; 84 | } 85 | 86 | Package package = Package(index); 87 | JC_Cap cap = package.getCap(); 88 | 89 | const jc_cap_package_info &pinfo_to_compare = cap.getHeader()->package; 90 | 91 | if (*pinfo == pinfo_to_compare) { 92 | return index; 93 | } 94 | } 95 | 96 | throw Exceptions::RuntimeException; 97 | } 98 | 99 | /* 100 | * Get the package index in the flash from import component offset. 101 | * 102 | * @param[offset] Offset of the package information in the current import 103 | * component 104 | */ 105 | const jpackage_ID_t 106 | Import_Handler::getPackageIndexFromOffset(const uint8_t offset) { 107 | auto aid = this->getPackageAID(offset); 108 | return this->getPackageIndex(aid); 109 | } 110 | 111 | } // namespace jcvm 112 | -------------------------------------------------------------------------------- /src/jc_bytecodes/bc_exceptions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "../debug.hpp" 29 | #include "../stack.hpp" 30 | #include "bytecodes.hpp" 31 | 32 | namespace jcvm { 33 | 34 | /** 35 | * Throw exception or error 36 | * 37 | * Format: 38 | * athrow 39 | * 40 | * Forms: 41 | * athrow = 147 (0x93) 42 | * 43 | * Stack: 44 | * ..., objectref -> objectref 45 | * 46 | * Description: 47 | * 48 | * The objectref must be of type reference and must refer to an object 49 | * that is an instance of class Throwable or of a subclass of Throwable. 50 | * It is popped from the operand stack. The objectref is then thrown by 51 | * searching the current frame (§3.5 Frames) for the most recent catch 52 | * clause that catches the class of objectref or one of its superclasses. 53 | * 54 | * If a catch clause is found, it contains the location of the code 55 | * intended to handle this exception. The pc register is reset to that 56 | * location, the operand stack of the current frame is cleared, objectref 57 | * is pushed back onto the operand stack, and execution continues. If no 58 | * appropriate clause is found in the current frame, that frame is popped, 59 | * the frame of its invoker is reinstated, and the objectref is rethrown. 60 | * 61 | * If no catch clause is found that handles this exception, the virtual 62 | * machine exits. 63 | * 64 | * Runtime Exception: 65 | * 66 | * If objectref is null, athrow throws a NullPointerException instead of 67 | * objectref. 68 | * 69 | * Notes: 70 | * 71 | * In some circumstances, the athrow instruction may throw a 72 | * SecurityException if the current context (§3.4 Contexts) is not the 73 | * owning context (§3.4 Contexts) of the object referenced by objectref. 74 | * The exact circumstances when the exception will be thrown are specified 75 | * in Chapter 6 of the Runtime Environment Specification, Java Card 3 76 | * Platform, v3.0.5, Classic Edition. 77 | */ 78 | void Bytecodes::bc_athrow() { 79 | jref_t objectref; 80 | Stack &stack = this->context.getStack(); 81 | 82 | TRACE_JCVM_DEBUG("ATHROW"); 83 | 84 | objectref = stack.pop_Reference(); 85 | this->doThrow(objectref); 86 | 87 | return; 88 | } 89 | 90 | /** 91 | * Throwing an exception 92 | * 93 | */ 94 | void Bytecodes::doThrow(jref_t objectref) { 95 | // TODO: Implementing this instruction 96 | throw Exceptions::NotYetImplemented; 97 | } 98 | 99 | } // namespace jcvm 100 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_static_field.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_STATIC_FIELD_HPP 29 | #define _JC_CAP_STATIC_FIELD_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_utils.hpp" 33 | #include "../jcvm_types/jcvmarray.hpp" 34 | #include "../types.hpp" 35 | 36 | namespace jcvm { 37 | 38 | struct __attribute__((__packed__)) jc_cap_array_init_info { 39 | /// Type of primitive array 40 | uint8_t type; 41 | /// Number of byte in the values array 42 | uint16_t count; 43 | /// Initial values of the static field array 44 | uint8_t value[/* count */]; 45 | 46 | JCVMArray values() const noexcept { 47 | return JCVMArray(NTOHS(count), value); 48 | } 49 | }; 50 | 51 | struct __attribute__((__packed__)) jc_cap_static_field_component { 52 | /// Component tag: COMPONENT_StaticField (8) 53 | uint8_t tag; 54 | /// Component size 55 | uint16_t size; 56 | /// Bytes required to represent the static fields 57 | uint16_t image_size; 58 | /// Number of reference type static fields 59 | uint16_t reference_count; 60 | /// Number of elements in the array_init array 61 | uint16_t array_init_count; 62 | /// The rest of the component 63 | uint8_t data[]; 64 | // { 65 | // /// Initial value of primitive types 66 | // struct jc_cap_array_init_info array_init [ /* array_init_count */ ]; 67 | // /// Number of bytes required to initialize the set of static fields 68 | // uint16_t default_value_count; 69 | // /// represents the number bytes in the non_default_values array 70 | // uint16_t non_default_value_count; 71 | // /// bytes of non-default initial values 72 | // uint8_t non_default_values [ /* non_default_values_count */ ]; 73 | // } 74 | 75 | uint16_t default_value_count() const noexcept { 76 | return BYTES_TO_SHORT( 77 | data[array_init_count * sizeof(jc_cap_array_init_info)], 78 | data[array_init_count * sizeof(jc_cap_array_init_info) + 1]); 79 | } 80 | 81 | uint16_t non_default_value_count() const noexcept { 82 | return BYTES_TO_SHORT( 83 | data[array_init_count * sizeof(jc_cap_array_init_info) + 84 | sizeof(uint16_t)], 85 | data[array_init_count * sizeof(jc_cap_array_init_info) + 86 | sizeof(uint16_t) + 1]); 87 | } 88 | 89 | JCVMArray non_default_values() const noexcept { 90 | return JCVMArray( 91 | non_default_value_count(), 92 | (data + array_init_count * sizeof(jc_cap_array_init_info) + 93 | 2 * sizeof(uint16_t))); 94 | } 95 | }; 96 | 97 | } // namespace jcvm 98 | 99 | #endif /* _JC_CAP_STATIC_FIELD_HPP */ 100 | -------------------------------------------------------------------------------- /src/frame.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _FRAME_HPP 29 | #define _FRAME_HPP 30 | 31 | #include "exceptions.hpp" 32 | #include "jc_config.h" 33 | #include "jcvm_types/list.hpp" 34 | #include "jcvm_types/pc_t.hpp" 35 | #include "types.hpp" 36 | 37 | namespace jcvm { 38 | 39 | class Frame { 40 | private: 41 | struct old_pc_t { 42 | bool isUsed; 43 | pc_t &pc; 44 | }; 45 | 46 | jword_t *fp; // frame base pointer 47 | jword_t *op; // operand stack base pointer 48 | jword_t *tos; // top of operand stack 49 | jword_t *eos; // end of operand stack (= last operand stack word) 50 | pc_t pc; // method program counter 51 | 52 | List old_pcs; 53 | 54 | public: 55 | /// default constructor 56 | Frame(jword_t *fp, jword_t *op, jword_t *tos, jword_t *eos, pc_t &pc) noexcept 57 | : fp(fp), op(op), tos(tos), eos(eos), pc(pc) {} 58 | // Frame(const Frame &frame) noexcept = default; 59 | Frame &operator=(const Frame &frame) = default; 60 | /// Return frame base pointer 61 | jword_t *getFP() const noexcept; 62 | /// Return operand stack base pointer 63 | jword_t *getOP() const noexcept; 64 | /// Return top of operand stack pointer 65 | jword_t *getTOS() const noexcept; 66 | /// Return end of operand stack pointer 67 | jword_t *getEOS() const noexcept; 68 | /// Return method program counter pointer 69 | pc_t &getPC() noexcept; 70 | /// Set frame base pointer 71 | void setFP(jword_t *fp) noexcept; 72 | /// Set operand stack base pointer 73 | void setOP(jword_t *op) noexcept; 74 | /// Set top of operand stack 75 | void setTOS(jword_t *tos) noexcept; 76 | /// Set end of operand stack 77 | void setEOS(jword_t *eos) noexcept; 78 | /// Set method program counter pointer 79 | void setPC(pc_t &pc) noexcept; 80 | /// Save PC value for jsr instruction 81 | uint8_t savePC() noexcept; 82 | /// Restore PC value for ret instruction 83 | pc_t &restorePC(const uint8_t index) 84 | #if !defined(JCVM_FIREWALL_CHECKS) && !defined(JCVM_ARRAY_SIZE_CHECK) 85 | noexcept 86 | #endif 87 | ; 88 | /// Pushing a value 89 | void push_Value(const jword_t value) 90 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 91 | noexcept 92 | #endif 93 | ; 94 | /// Popping a value 95 | jword_t pop_Value() 96 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 97 | noexcept 98 | #endif 99 | ; 100 | /// Reading a Local Variable 101 | jword_t readLocal_Value(const uint8_t local_number) 102 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 103 | noexcept 104 | #endif 105 | ; 106 | /// Writing to Local Variable 107 | void writeLocal_Value(const uint8_t local_number, const int16_t value) 108 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 109 | noexcept 110 | #endif 111 | ; 112 | }; 113 | 114 | } // namespace jcvm 115 | 116 | #endif /* _FRAME_HPP */ 117 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_export.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_EXPORT_HPP 29 | #define _JC_CAP_EXPORT_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_class_export_info { 38 | /// Offset of the exported class component 39 | uint16_t class_offset; 40 | /// Number of elements in the static_field_offsets array 41 | uint8_t static_field_count; 42 | /// Number of elements in the static_method_offsets array 43 | uint8_t static_method_count; 44 | uint16_t data[/* static_field_count + static_method_count */]; 45 | // { 46 | // /// List each static field in the static field component 47 | // uint16_t static_field_offsets [/* static_field_count */]; 48 | // /// List each static method in the Method component 49 | // uint16_t static_method_offsets [/* static_method_count */]; 50 | // } 51 | 52 | const JCVMArray static_field_offsets() const noexcept { 53 | return JCVMArray(static_field_count, data); 54 | } 55 | 56 | const JCVMArray static_method_offsets() const noexcept { 57 | return JCVMArray( 58 | static_method_count, (data + static_field_count * sizeof(uint16_t))); 59 | } 60 | 61 | uint16_t getSizeOf() const noexcept { 62 | return sizeof(jc_cap_class_export_info) + 63 | (static_field_count + static_method_count) * sizeof(uint16_t); 64 | } 65 | }; 66 | 67 | struct __attribute__((__packed__)) jc_cap_export_component { 68 | /// Component tag: COMPONENT_Export (10) 69 | uint8_t tag; 70 | /// Component size 71 | uint16_t size; 72 | /// Number of entries in the class_exports table 73 | uint8_t class_count; 74 | /// List of each public classes and public interface defined 75 | uint8_t class_exports[/* class_count */]; 76 | 77 | const jc_cap_class_export_info &classexport(const uint16_t index) const 78 | #ifdef JCVM_ARRAY_SIZE_CHECK 79 | noexcept(false) 80 | #else 81 | noexcept 82 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 83 | { 84 | #ifdef JCVM_ARRAY_SIZE_CHECK 85 | 86 | if (this->class_count <= index) { 87 | throw Exceptions::SecurityException; 88 | } 89 | 90 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 91 | 92 | uint16_t offset = 0; 93 | 94 | for (uint16_t foo = 0; foo < index; ++foo) { 95 | const uint8_t *class_export_info = class_exports + offset; 96 | auto exported_class = 97 | reinterpret_cast(class_export_info); 98 | offset += exported_class->getSizeOf(); 99 | } 100 | 101 | const jc_cap_class_export_info *ret = 102 | reinterpret_cast(class_exports + 103 | offset); 104 | return *ret; 105 | } 106 | }; 107 | 108 | } // namespace jcvm 109 | 110 | #endif /* _JC_CAP_EXPORT_HPP */ 111 | -------------------------------------------------------------------------------- /src/jc_types/jc_instance.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_INSTANCE_HPP 29 | #define _JC_INSTANCE_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_handlers/package.hpp" 33 | #include "../jc_utils.hpp" 34 | #include "../jcvm_types/jcvmarray.hpp" 35 | #include "../types.hpp" 36 | #include "jc_field.hpp" 37 | #include "jc_object.hpp" 38 | #include "jref_t.hpp" 39 | 40 | namespace jcvm { 41 | 42 | namespace fs { 43 | struct Tag; // Forward declaration of Tag 44 | } 45 | 46 | class JC_Instance : public JC_Object { 47 | private: 48 | jpackage_ID_t packageID; 49 | jclass_index_t claz; 50 | 51 | /** 52 | * Instance fields' values. Each element are encoded on one words (SHORT 53 | * and REFERENCE). According to the specification, the INTEGER, are 54 | * encoded on 2 words. 55 | */ 56 | JCVMArray *fields = nullptr; // instance_length-length array 57 | 58 | fs::Tag recomputeOriginalTag() const noexcept; 59 | 60 | public: 61 | JC_Instance(Heap &owner, const Package &package_owner, 62 | const jc_cp_offset_t instantiated_class) noexcept; 63 | JC_Instance(Heap &owner, const jpackage_ID_t packageID, 64 | const jclass_index_t claz_index) noexcept; 65 | JC_Instance(Heap &owner, const jpackage_ID_t packageID, 66 | const jclass_index_t claz_index, const fs::Tag &tag) noexcept; 67 | ~JC_Instance() noexcept; 68 | 69 | /// Get package ID 70 | jpackage_ID_t getPackageID() const noexcept; 71 | /// Get class index 72 | jclass_index_t getClassIndex() const noexcept; 73 | /// Set package ID 74 | void setPackageID(const jpackage_ID_t packageID) noexcept; 75 | /// Set class index 76 | void setClassIndex(const jclass_index_t class_index) noexcept; 77 | 78 | /// Fetch byte or boolean from object. 79 | const jbyte_t getField_Byte(const uint16_t index); 80 | /// Fetch short from object. 81 | const jshort_t getField_Short(const uint16_t index); 82 | #ifdef JCVM_INT_SUPPORTED 83 | /// Fetch int from object. 84 | const jint_t getField_Int(const uint16_t index); 85 | #endif /* JCVM_INT_SUPPORTED */ 86 | /// Fetch reference from object. 87 | const jref_t getField_Reference(const uint16_t index); 88 | 89 | /// set byte or boolean field from object. 90 | void setField_Byte(const uint16_t index, const jbyte_t value); 91 | /// set short field from object. 92 | void setField_Short(const uint16_t index, const jshort_t value); 93 | #ifdef JCVM_INT_SUPPORTED 94 | /// set int field from object. 95 | void setField_Int(const uint16_t index, const jint_t value); 96 | #endif /* JCVM_INT_SUPPORTED */ 97 | /// set reference field from object. 98 | void setField_Reference(uint16_t index, jref_t ref); 99 | 100 | /// Get the number of instance field. 101 | auto getNumberOfFields() const noexcept -> decltype(fields->size()); 102 | /// Get fields arrays 103 | auto getFields() const noexcept -> decltype(fields); 104 | }; 105 | 106 | } // namespace jcvm 107 | 108 | #endif /* _JC_INSTANCE_HPP */ 109 | -------------------------------------------------------------------------------- /src/jc_utils.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_UTILS_HPP 29 | #define _JC_UTILS_HPP 30 | 31 | #include "jc_config.h" 32 | #include "types.hpp" 33 | 34 | namespace jcvm { 35 | 36 | #define MAX(a, b) \ 37 | ({ \ 38 | __typeof__(a) _a = (a); \ 39 | __typeof__(b) _b = (b); \ 40 | _a > _b ? _a : _b; \ 41 | }) 42 | 43 | #define MIN(a, b) \ 44 | ({ \ 45 | __typeof__(a) _a = (a); \ 46 | __typeof__(b) _b = (b); \ 47 | _a > _b ? _b : _a; \ 48 | }) 49 | 50 | #define LOW_NIBBLE(x) static_cast(x & 0x0F) 51 | #define HIGH_NIBBLE(x) LOW_NIBBLE(x >> 4) 52 | 53 | #define LOW_BYTE_SHORT(x) static_cast(x & 0x00FF) 54 | #define HIGH_BYTE_SHORT(x) LOW_BYTE_SHORT(x >> 8) 55 | #define BYTE_TO_SHORT(x) static_cast(x & 0x00FF) 56 | #define BYTE_TO_WORD BYTE_TO_SHORT 57 | 58 | #ifdef JCVM_INT_SUPPORTED 59 | #define INT_2_LSSHORTS(x) static_cast(x & 0x0000FFFF) 60 | #define INT_2_MSSHORTS(x) INT_2_LSSHORTS(x >> 16) 61 | #endif /* JCVM_INT_SUPPORTED */ 62 | 63 | #define BYTES_TO_SHORT(x, y) static_cast((x << 8) | (y & 0x00FF)) 64 | 65 | #ifdef JCVM_INT_SUPPORTED 66 | #define SHORTS_TO_INT(x, y) static_cast((x << 16) | (y & 0x0FFFF)) 67 | #define BYTES_TO_INT(w, x, y, z) \ 68 | ((BYTES_TO_SHORT(w, x) << 16) | (BYTES_TO_SHORT(y, z) & 0x0FFFF)) 69 | #endif /* JCVM_INT_SUPPORTED */ 70 | 71 | #define CLEAR_BYTE_MSB(x) (x & 0x7F) 72 | 73 | // This piece of code was adapted from 74 | // https://bytes.com/topic/c/answers/128237-portable-endianess 75 | #if defined(NVM_BIG_ENDIAN) && !defined(NVM_LITTLE_ENDIAN) 76 | 77 | #define HTONS(A) (A) 78 | #define HTONI(A) (A) 79 | #define NTOHS(A) (A) 80 | #define NTOHI(A) (A) 81 | 82 | #elif defined(NVM_LITTLE_ENDIAN) && !defined(NVM_BIG_ENDIAN) 83 | 84 | #define HTONS(A) \ 85 | static_cast(((A & 0xff00) >> 8) | ((A & 0x00ff) << 8)) 86 | 87 | #define HTONI(A) \ 88 | static_cast(((A & 0xff000000) >> 24) | ((A & 0x00ff0000) >> 8) | \ 89 | ((A & 0x0000ff00) << 8) | ((A & 0x000000ff) << 24)) 90 | 91 | #define NTOHS HTONS 92 | #define NTOHI HTONI 93 | 94 | #else 95 | 96 | #error \ 97 | "Either NVM_BIG_ENDIAN or NVM_LITTLE_ENDIAN must be #defined, but not both." 98 | 99 | #endif 100 | 101 | } // namespace jcvm 102 | 103 | #endif /* _JC_UTILS_HPP */ 104 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_export.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jc_export.hpp" 29 | 30 | namespace jcvm { 31 | 32 | /* 33 | * Get an exported class from a class offset 34 | * 35 | * @param[class_export_offset] exported class offset to resolve. 36 | * 37 | * @return class_export associated to the input offset. 38 | */ 39 | const jc_cap_class_export_info & 40 | Export_Handler::getExportedClass(const uint16_t class_export_offset) const 41 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 42 | noexcept 43 | #endif 44 | { 45 | const JC_Cap &cap = this->package.getCap(); 46 | const jc_cap_export_component *export_component = cap.getExport(); 47 | 48 | #ifdef JCVM_DYNAMIC_CHECKS_CAP 49 | 50 | if (export_component == nullptr) { // No export component found! 51 | throw Exceptions::SecurityException; 52 | } 53 | 54 | #endif /* JCVM_DYNAMIC_CHECKS_CAP */ 55 | 56 | return export_component->classexport(class_export_offset); 57 | } 58 | 59 | /* 60 | * Get an exported class index on the class component 61 | * 62 | * @param[class_export_offset] exported class offset to resolve. 63 | * 64 | * @return class offset on the class component. 65 | */ 66 | const jclass_index_t 67 | Export_Handler::getExportedClassOffset(const uint16_t class_export_offset) const 68 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 69 | noexcept 70 | #endif 71 | { 72 | auto class_import_info = this->getExportedClass(class_export_offset); 73 | 74 | return static_cast(class_import_info.class_offset); 75 | } 76 | 77 | /** 78 | * Get static method offset in the method component from static method offset 79 | * in the Export component. 80 | * 81 | * @param[class_export_offset] exported class offset to resolve. 82 | * @param[static_method_offset] static method offset. 83 | * @return static method offset in the method component. 84 | */ 85 | uint16_t Export_Handler::getExportedStaticMethodOffset( 86 | const uint16_t class_export_offset, 87 | const uint8_t static_method_offset) const 88 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 89 | noexcept 90 | #endif 91 | { 92 | const jc_cap_class_export_info &exported_class = 93 | this->getExportedClass(class_export_offset); 94 | 95 | const JCVMArray method_offsets = 96 | exported_class.static_method_offsets(); 97 | 98 | return HTONS(method_offsets.at(static_method_offset)); 99 | } 100 | 101 | /** 102 | * Get static field offset in the Static field component from static method 103 | * offset in the Export component. 104 | * 105 | * @param[class_export_offset] exported class offset to resolve. 106 | * @param[static_field_offset] static method offset. 107 | * @return static field offset in the Static Field component. 108 | */ 109 | uint16_t Export_Handler::getExportedStaticFieldOffset( 110 | const uint16_t class_export_offset, const uint8_t static_field_offset) const 111 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 112 | noexcept 113 | #endif 114 | { 115 | const jc_cap_class_export_info &exported_class = 116 | this->getExportedClass(class_export_offset); 117 | 118 | const JCVMArray field_offsets = 119 | exported_class.static_field_offsets(); 120 | 121 | return HTONS(field_offsets.at(static_field_offset)); 122 | } 123 | 124 | } // namespace jcvm 125 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_cap.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_HPP 29 | #define _JC_CAP_HPP 30 | 31 | #include "../jc_cap/jc_cap_applet.hpp" 32 | #include "../jc_cap/jc_cap_class.hpp" 33 | #include "../jc_cap/jc_cap_cp.hpp" 34 | #include "../jc_cap/jc_cap_descriptor.hpp" 35 | #include "../jc_cap/jc_cap_directory.hpp" 36 | #include "../jc_cap/jc_cap_export.hpp" 37 | #include "../jc_cap/jc_cap_header.hpp" 38 | #include "../jc_cap/jc_cap_import.hpp" 39 | #include "../jc_cap/jc_cap_method.hpp" 40 | #include "../jc_cap/jc_cap_reference_location.hpp" 41 | #include "../jc_cap/jc_cap_static_field.hpp" 42 | #include "../jc_config.h" 43 | #include "../types.hpp" 44 | 45 | namespace jcvm { 46 | // FIXME: Currently, only the CAP file version 2.1 is implemented 47 | class JC_Cap { 48 | private: 49 | /// Pointer to the header component 50 | const jc_cap_header_component *header_comp = nullptr; 51 | /// Pointer to the directory component 52 | const jc_cap_directory_component *directory_comp = nullptr; 53 | /// Pointer to the import component 54 | const jc_cap_import_component *import_comp = nullptr; 55 | /// Pointer to the applet component 56 | const jc_cap_applet_component *applet_comp = nullptr; 57 | /// Pointer to the class component 58 | const jc_cap_class_component *class_comp = nullptr; 59 | /// Pointer to the method component 60 | const jc_cap_method_component *method_comp = nullptr; 61 | /// Pointer to the static field component 62 | const jc_cap_static_field_component *staticField_comp = nullptr; 63 | /// Pointer to the export component 64 | const jc_cap_export_component *export_comp = nullptr; 65 | /// Pointer to the constant pool component 66 | const jc_cap_constant_pool_component *constantPool_comp = nullptr; 67 | /// Pointer to the reference location component 68 | const jc_cap_reference_location_component *referenceLocation_comp = nullptr; 69 | /// Pointer to the descriptor component 70 | const jc_cap_descriptor_component *descriptor_comp = nullptr; 71 | 72 | public: 73 | /// default constructor 74 | JC_Cap(uint16_t length, const uint8_t *cap_file); 75 | JC_Cap(const JC_Cap &cap) noexcept = default; 76 | /// Copy assignment operator 77 | JC_Cap &operator=(const JC_Cap &cap) noexcept; 78 | /// Move assignment operator 79 | JC_Cap &operator=(const JC_Cap &&cap) noexcept; 80 | 81 | /// Equality operator 82 | bool operator==(JC_Cap &cap) const noexcept; 83 | 84 | /// Get Header component 85 | const jc_cap_header_component *getHeader() const noexcept; 86 | /// Get Directory component 87 | const jc_cap_directory_component *getDirectory() const noexcept; 88 | /// Get Import component 89 | const jc_cap_import_component *getImport() const noexcept; 90 | /// Get Applet component 91 | const jc_cap_applet_component *getApplet() const noexcept; 92 | /// Get Class component 93 | const jc_cap_class_component *getClass() const noexcept; 94 | /// Get Method component 95 | const jc_cap_method_component *getMethod() const noexcept; 96 | /// Get StaticField component 97 | const jc_cap_static_field_component *getStaticField() const noexcept; 98 | /// Get Export component 99 | const jc_cap_export_component *getExport() const noexcept; 100 | /// Get ConstantPool component 101 | const jc_cap_constant_pool_component *getConstantPool() const noexcept; 102 | /// Get ReferenceLocation component 103 | const jc_cap_reference_location_component *getReferenceLocation() const 104 | noexcept; 105 | /// Get Descriptor component 106 | const jc_cap_descriptor_component *getDescriptor() const noexcept; 107 | }; 108 | 109 | } // namespace jcvm 110 | 111 | #endif /* _JC_CAP_HPP */ 112 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_method.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jc_method.hpp" 29 | #include "../heap.hpp" 30 | #include "../stack.hpp" 31 | 32 | namespace jcvm { 33 | 34 | /** 35 | * Get method from offset. 36 | * 37 | * @param[method_offset] method offset to resolve. 38 | * 39 | * @return method from method_offset with the type struct jc_cap_method_info or 40 | * struct jc_cap_extended_method_info 41 | */ 42 | const uint8_t *Method_Handler::getMethodFromOffset(const uint16_t method_offset) 43 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 44 | noexcept 45 | #endif 46 | { 47 | auto cap = this->package.getCap(); 48 | 49 | #ifdef JCVM_DYNAMIC_CHECKS_CAP 50 | 51 | if (cap.getMethod() == nullptr) { 52 | throw Exceptions::SecurityException; 53 | } 54 | 55 | #endif /* JCVM_DYNAMIC_CHECKS_CAP */ 56 | 57 | const JCVMArray methods = cap.getMethod()->methods(); 58 | 59 | // NOTE: The method offset starts from 1. 60 | return &(methods.at(method_offset - 1)); 61 | } 62 | 63 | /** 64 | * Calling a method. 65 | * 66 | * @param[method_to_call] pointer to the method to call. 67 | * @param[isStaticMethod] is a static method? 68 | */ 69 | void Method_Handler::callMethod(const uint8_t *const method_to_call, 70 | const jbool_t isStaticMethod) 71 | #if !defined(JCVM_DYNAMIC_CHECKS_CAP) && !defined(JCVM_FIREWALL_CHECKS) 72 | noexcept 73 | #endif 74 | { 75 | uint8_t nargs, max_stack, max_locals; 76 | const uint8_t *new_pc; 77 | 78 | #ifdef JCVM_DYNAMIC_CHECKS_CAP 79 | 80 | if (IS_ABSTRACT_METHOD(method_to_call)) { 81 | throw Exceptions::SecurityException; 82 | } 83 | 84 | #endif /* JCVM_DYNAMIC_CHECKS_CAP */ 85 | 86 | if (IS_EXTENDED_METHOD(method_to_call)) { 87 | auto method_to_run = 88 | reinterpret_cast(method_to_call); 89 | 90 | max_stack = method_to_run->method_header.max_stack; 91 | nargs = method_to_run->method_header.nargs; 92 | max_locals = method_to_run->method_header.max_locals; 93 | new_pc = method_to_run->bytecodes; 94 | } else { // normal method header 95 | auto method_to_run = 96 | reinterpret_cast(method_to_call); 97 | 98 | max_stack = LOW_NIBBLE(method_to_run->method_header.max_stack); 99 | nargs = LOW_NIBBLE(method_to_run->method_header.nargs); 100 | max_locals = LOW_NIBBLE(method_to_run->method_header.max_locals); 101 | new_pc = method_to_run->bytecodes; 102 | } 103 | 104 | #ifdef JCVM_FIREWALL_CHECKS 105 | 106 | if ((isStaticMethod == FALSE) && (nargs == 0)) { 107 | throw Exceptions::SecurityException; 108 | } 109 | 110 | #endif /* JCVM_FIREWALL_CHECKS */ 111 | 112 | // pushing the new frame 113 | this->context.getStack().push_Frame(nargs, max_locals, max_stack, new_pc); 114 | 115 | // and updating executed package ID. 116 | 117 | this->context.changePackageID(this->package.getPackageID()); 118 | 119 | return; 120 | } 121 | 122 | /** 123 | * Call a virtual method 124 | * 125 | * @param[method_offset] offset in the method component where the method to 126 | * executed is located. 127 | */ 128 | void Method_Handler::callVirtualMethod(const uint16_t method_offset) { 129 | const uint8_t *method_to_call = this->getMethodFromOffset(method_offset); 130 | this->callMethod(method_to_call); 131 | return; 132 | } 133 | 134 | /** 135 | * Call a static method 136 | * 137 | * @param[method_offset] offset in the method component where the method to 138 | * executed is located. 139 | */ 140 | void Method_Handler::callStaticMethod(const uint16_t method_offset) { 141 | const uint8_t *method_to_call = this->getMethodFromOffset(method_offset); 142 | this->callMethod(method_to_call, TRUE); 143 | return; 144 | } 145 | 146 | } // namespace jcvm 147 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_static.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jc_static.hpp" 29 | #include "../exceptions.hpp" 30 | #include "../heap.hpp" 31 | #include "flashmemory.hpp" 32 | 33 | namespace jcvm { 34 | 35 | /** 36 | * Get static byte value. 37 | * 38 | * @param[index] static byte index in the current package. 39 | * @return the static byte value. 40 | */ 41 | jbyte_t Static_Handler::getPersistentByte(const uint16_t index) const { 42 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 43 | this->package.getPackageID(), index); 44 | return FlashMemory_Handler::getPersistentField_Byte(tag); 45 | } 46 | 47 | /** 48 | * Get static short value. 49 | * 50 | * @param[index] static short index in the current package. 51 | * @return the static short value. 52 | */ 53 | jshort_t Static_Handler::getPersistentShort(const uint16_t index) const { 54 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 55 | this->package.getPackageID(), index); 56 | return FlashMemory_Handler::getPersistentField_Short(tag); 57 | } 58 | 59 | #ifdef JCVM_INT_SUPPORTED 60 | /** 61 | * Get static integer value. 62 | * 63 | * @param[index] static integer index in the current package. 64 | * @return the static integer value. 65 | */ 66 | jint_t Static_Handler::getPersistentInt(const uint16_t index) const { 67 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 68 | this->package.getPackageID(), index); 69 | return FlashMemory_Handler::getPersistentField_Int(tag); 70 | } 71 | #endif /* JCVM_INT_SUPPORTED */ 72 | 73 | /* 74 | * Read static serialized instance or array. 75 | * 76 | * @param[index] static index in the current package. 77 | * @return static serialized instance or array. 78 | */ 79 | jref_t Static_Handler::getPersistentRef(const uint16_t index, 80 | Heap &heap) const { 81 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 82 | this->package.getPackageID(), index); 83 | 84 | return FlashMemory_Handler::getPersistentField_Reference(tag, heap); 85 | } 86 | 87 | /** 88 | * Set static byte value. 89 | * 90 | * @param[index] static byte index in the current package. 91 | * @param[value] new the static byte value. 92 | */ 93 | void Static_Handler::setPersistentByte(const uint16_t index, 94 | const jbyte_t value) { 95 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 96 | this->package.getPackageID(), index); 97 | 98 | FlashMemory_Handler::setPersistentField_Byte(tag, value); 99 | } 100 | 101 | /** 102 | * Set static short value. 103 | * 104 | * @param[index] static short index in the current package. 105 | * @param[value] new the static short value. 106 | */ 107 | void Static_Handler::setPersistentShort(const uint16_t index, 108 | const jshort_t value) { 109 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 110 | this->package.getPackageID(), index); 111 | 112 | FlashMemory_Handler::setPersistentField_Short(tag, value); 113 | } 114 | 115 | #ifdef JCVM_INT_SUPPORTED 116 | /** 117 | * Set static integer value. 118 | * 119 | * @param[index] static integer index in the current package. 120 | * @param[value] new the static integer value. 121 | */ 122 | void Static_Handler::setPersistentInt(const uint16_t index, 123 | const jint_t value) { 124 | fs::Tag tag = FlashMemory_Handler::getStaticFieldTag( 125 | this->package.getPackageID(), index); 126 | 127 | JCVMArray data(sizeof(jint_t)); 128 | data[0] = HIGH_BYTE_SHORT(INT_2_MSSHORTS(value)); 129 | data[1] = LOW_BYTE_SHORT(INT_2_MSSHORTS(value)); 130 | data[2] = HIGH_BYTE_SHORT(INT_2_LSSHORTS(value)); 131 | data[3] = LOW_BYTE_SHORT(INT_2_LSSHORTS(value)); 132 | 133 | FlashMemory_Handler::setPersistentField_Int(tag, value); 134 | } 135 | #endif /* JCVM_INT_SUPPORTED */ 136 | 137 | } // namespace jcvm 138 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_class.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CLASS_HPP 29 | #define _JC_CLASS_HPP 30 | 31 | #include "../exceptions.hpp" 32 | #include "../jc_cap/jc_cap_cp.hpp" 33 | #include "../jc_config.h" 34 | #include "../jc_utils.hpp" 35 | #include "../types.hpp" 36 | #include "jc_component.hpp" 37 | 38 | #include 39 | 40 | namespace jcvm { 41 | 42 | class Class_Handler : public Component_Handler { 43 | private: 44 | /// Get a class package method offset from a class' package method token. 45 | std::pair getPublicMethodOffset( 46 | const jc_cap_virtual_method_ref_info virtual_method_ref_info) 47 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 48 | noexcept 49 | #endif 50 | ; 51 | 52 | /// Do get a class public method offset from a class' public method token. 53 | std::pair 54 | doGetPublicMethodOffset(Package &package, const jc_cap_class_info *claz, 55 | uint8_t public_method_offset) 56 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 57 | noexcept 58 | #endif 59 | ; 60 | 61 | /// Get a class package method offset from a class' package method token. 62 | std::pair getPackageMethodOffset( 63 | const jc_cap_virtual_method_ref_info virtual_method_ref_info) 64 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 65 | noexcept 66 | #endif 67 | ; 68 | 69 | /** 70 | * Check if two interfaces (interface_in and interface_out) have a hierarchy 71 | * link together. This function returns TRUE when interface_in is the 72 | * daughter of interface_out. 73 | */ 74 | static jbool_t 75 | checkInterfaceCast(const std::pair interface_in, 76 | const std::pair interface_out) 77 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 78 | noexcept 79 | #endif 80 | ; 81 | 82 | public: 83 | Class_Handler(Package package) : Component_Handler(package){}; 84 | 85 | /// do check interface type compatibility 86 | static jbool_t 87 | docheckcast(const std::pair jtype_in, 88 | const std::pair jtype_out) 89 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 90 | noexcept 91 | #endif 92 | ; 93 | 94 | /// Get the reference to the Object class from an objectref. 95 | std::pair 96 | getObjectClassFromAnObjectRef(const jc_cap_class_ref classref) 97 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 98 | noexcept 99 | #endif 100 | ; 101 | 102 | /// Get public or package method offset from a class' package method token. 103 | std::pair 104 | getMethodOffset(const jc_cap_virtual_method_ref_info virtual_method_ref_info) 105 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 106 | noexcept 107 | #endif 108 | ; 109 | 110 | /// Get a class' implemented interface method offset from a class' package 111 | /// method token. 112 | std::pair getImplementedInterfaceMethodOffset( 113 | const jc_cap_class_ref class_ref, const jc_cap_class_ref interface, 114 | const uint8_t implemented_interface_method_number, 115 | const bool isArray = false) 116 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 117 | noexcept 118 | #endif 119 | ; 120 | 121 | /// Get the instance field size for an instantiated class. 122 | const uint16_t getInstanceFieldsSize(const jclass_index_t claz_index) const 123 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 124 | noexcept 125 | #endif 126 | ; 127 | }; 128 | 129 | } // namespace jcvm 130 | #endif /* _JC_CLASS_HPP */ 131 | -------------------------------------------------------------------------------- /src/jc_types/jref_t.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "jref_t.hpp" 29 | #include "../jc_handlers/flashmemory.hpp" 30 | 31 | namespace jcvm { 32 | 33 | /** 34 | * Default constructor. 35 | * 36 | * @param[value] Value to initialise the jref_t object. 37 | */ 38 | jref_t::jref_t(uint16_t value) noexcept : value(value){}; 39 | 40 | /** 41 | * Copy constructor. 42 | * 43 | * @param[in] jref_t object to copy; 44 | * @return copied object. 45 | */ 46 | jref_t &jref_t::operator=(const jref_t &in) { 47 | this->value.packed = in.value.packed; 48 | return *this; 49 | } 50 | 51 | /** 52 | * Get a compact version of this class. 53 | * 54 | * @return the compact version of this class. 55 | */ 56 | uint16_t jref_t::compact() const noexcept { return this->value.packed; } 57 | 58 | /* 59 | * Is an array? 60 | * 61 | * @return true if jref is an array 62 | */ 63 | bool jref_t::isArray() const noexcept { return this->value.unpacked.isArray; } 64 | 65 | /* 66 | * Set as an array 67 | * 68 | * @return true if jref is an array 69 | */ 70 | void jref_t::setAsArray(const bool isArray) noexcept { 71 | this->value.unpacked.isArray = isArray; 72 | } 73 | 74 | /* 75 | * Is an instance? 76 | * 77 | * @return true if jref is an instance 78 | */ 79 | bool jref_t::isInstance() const noexcept { 80 | return !this->value.unpacked.isArray; 81 | } 82 | 83 | /* 84 | * Set as an instance 85 | * 86 | * @return true if jref is an instance 87 | */ 88 | void jref_t::setAsInstance(const bool isInstance) noexcept { 89 | this->value.unpacked.isArray = !isInstance; 90 | } 91 | 92 | /** 93 | * Get reference object. 94 | * 95 | * @return the reference object. 96 | */ 97 | uint16_t jref_t::getOffset() const noexcept { 98 | return this->value.unpacked.offset; 99 | } 100 | 101 | /** 102 | * Set reference object. 103 | * 104 | * @param[offset] new offset flag. 105 | */ 106 | void jref_t::setOffset(const uint16_t offset) noexcept { 107 | this->value.unpacked.offset = offset; 108 | } 109 | 110 | /** 111 | * Is a Java Null pointer. 112 | * 113 | * @return True if it is a Java Card Null pointer. 114 | */ 115 | bool jref_t::isNullPointer() const noexcept { 116 | return (this->value.unpacked.offset == 0); 117 | } 118 | 119 | /** 120 | * Equality operator. 121 | * 122 | * @param[ref] the ref to compare. 123 | * @return the equality comparison. 124 | */ 125 | bool jref_t::operator==(const jref_t &ref) const noexcept { 126 | return (this->value.packed == ref.value.packed); 127 | } 128 | 129 | /** 130 | * Inequality operator. 131 | * 132 | * @param[ref] the ref to compare. 133 | * @return the inequality comparison. 134 | */ 135 | bool jref_t::operator!=(const jref_t &ref) const noexcept { 136 | return (this->value.packed != ref.value.packed); 137 | } 138 | 139 | /** 140 | * Less than operator. 141 | * 142 | * @param[ref] the ref to compare. 143 | * @return the less than comparison. 144 | */ 145 | bool jref_t::operator<(const jref_t &ref) const noexcept { 146 | return (this->value.packed < ref.value.packed); 147 | } 148 | 149 | /** 150 | * Less than or equality operator. 151 | * 152 | * @param[ref] the ref to compare. 153 | * @return the less than or equal comparison. 154 | */ 155 | bool jref_t::operator<=(const jref_t &ref) const noexcept { 156 | return (this->value.packed <= ref.value.packed); 157 | } 158 | 159 | /** 160 | * Greater than operator. 161 | * 162 | * @param[ref] the ref to compare. 163 | * @return the greater than comparison. 164 | */ 165 | bool jref_t::operator>(const jref_t &ref) const noexcept { 166 | return (this->value.packed > ref.value.packed); 167 | } 168 | 169 | /** 170 | * Greater than or equality operator. 171 | * 172 | * @param[ref] the ref to compare. 173 | * @return the greater than or equal comparison. 174 | */ 175 | bool jref_t::operator>=(const jref_t &ref) const noexcept { 176 | return (this->value.packed >= ref.value.packed); 177 | } 178 | 179 | } // namespace jcvm 180 | -------------------------------------------------------------------------------- /src/jcvm_types/jcvmarray.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JCVMARRAY_HPP 29 | #define _JCVMARRAY_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../types.hpp" 33 | 34 | #ifdef JCVM_ARRAY_SIZE_CHECK 35 | #include "../exceptions.hpp" 36 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 37 | 38 | namespace jcvm { 39 | 40 | template class JCVMArray { 41 | private: 42 | uint16_t length; 43 | bool allocated_data; 44 | T *array; 45 | 46 | public: 47 | /* 48 | * Default class constructor. 49 | */ 50 | JCVMArray(const uint16_t length) noexcept { 51 | this->length = length; 52 | 53 | if (this->length > 0) { 54 | this->array = new T[length]{}; 55 | this->allocated_data = true; 56 | } else { 57 | this->allocated_data = false; 58 | } 59 | } 60 | 61 | JCVMArray(const uint16_t length, T *data) noexcept { 62 | this->length = length; 63 | this->array = data; 64 | this->allocated_data = false; 65 | } 66 | 67 | /* 68 | * Default class destructor. 69 | */ 70 | ~JCVMArray() noexcept { 71 | if (this->allocated_data) { 72 | delete[] this->array; 73 | } 74 | } 75 | 76 | /* 77 | * Access specified element with bounds checking. 78 | * 79 | * @param[index] Get the indexed element. 80 | * @return Get the indexed element. 81 | */ 82 | T &operator[](uint16_t index) 83 | #ifndef JCVM_ARRAY_SIZE_CHECK 84 | noexcept 85 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 86 | { 87 | return this->at(index); 88 | } 89 | 90 | /* 91 | * Access specified element with bounds checking. 92 | * 93 | * @param[index] Get the indexed element. 94 | * @return Get the indexed element. 95 | */ 96 | constexpr T &operator[](uint16_t index) const 97 | #ifndef JCVM_ARRAY_SIZE_CHECK 98 | noexcept 99 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 100 | { 101 | return this->at(index); 102 | } 103 | 104 | /* 105 | * Access specified element with bounds checking. 106 | * 107 | * @param[index] Get the indexed element. 108 | * @return Get the indexed element. 109 | */ 110 | T &at(uint16_t index) 111 | #ifndef JCVM_ARRAY_SIZE_CHECK 112 | noexcept 113 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 114 | { 115 | #ifdef JCVM_ARRAY_SIZE_CHECK 116 | 117 | if (index >= this->length) { 118 | throw Exceptions::IndexOutOfBoundsException; 119 | } 120 | 121 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 122 | return this->array[index]; 123 | } 124 | 125 | /* 126 | * Access specified element with bounds checking. 127 | * 128 | * @param[index] Get the indexed element. 129 | * @return Get the indexed element. 130 | */ 131 | constexpr T &at(uint16_t index) const 132 | #ifndef JCVM_ARRAY_SIZE_CHECK 133 | noexcept 134 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 135 | { 136 | #ifdef JCVM_ARRAY_SIZE_CHECK 137 | 138 | if (index >= this->length) { 139 | throw Exceptions::IndexOutOfBoundsException; 140 | } 141 | 142 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 143 | return this->array[index]; 144 | } 145 | 146 | /* 147 | * Direct access to the underlying array. 148 | * 149 | * @return Pointer to the underlying array. 150 | */ 151 | T *data() noexcept { return this->array; } 152 | 153 | /* 154 | * Direct access to the underlying array. 155 | * 156 | * @return Constant pointer to the underlying array. 157 | */ 158 | const T *data() const noexcept { return this->array; } 159 | 160 | /* 161 | * Returns the maximum possible number of elements 162 | * 163 | * @return the maximum possible number of elements 164 | */ 165 | const uint16_t size() const noexcept { return this->length; } 166 | 167 | /* 168 | * Assigns the given value value to all elements in the container. 169 | * 170 | * @param[value] the value used to fill the array. 171 | */ 172 | void fill(const T &value) noexcept { 173 | T *word = this->array; 174 | 175 | for (int index = 0; index < this->size(); ++index) { 176 | *word = value; 177 | } 178 | } 179 | }; 180 | 181 | } // namespace jcvm 182 | 183 | #endif /* _JCVMARRAY_HPP */ 184 | -------------------------------------------------------------------------------- /src/jc_handlers/jc_cp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CONSTANT_POOL_HPP 29 | #define _JC_CONSTANT_POOL_HPP 30 | 31 | #include "../jc_config.h" 32 | 33 | #include "../exceptions.hpp" 34 | #include "../jc_cap/jc_cap_cp.hpp" 35 | #include "../jc_utils.hpp" 36 | #include "../types.hpp" 37 | #include "jc_component.hpp" 38 | #include "package.hpp" 39 | 40 | #include 41 | 42 | namespace jcvm { 43 | 44 | class ConstantPool_Handler : public Component_Handler { 45 | public: 46 | /// Default constructor 47 | ConstantPool_Handler(Package package) noexcept : Component_Handler(package){}; 48 | 49 | std::pair 50 | getClassInformation(const jc_cp_offset_t instantiated_class) 51 | #ifndef JCVM_ARRAY_SIZE_CHECK 52 | noexcept 53 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 54 | ; 55 | 56 | /// Get a cp_entry 57 | const jc_cap_constant_pool_info getCPEntry(const jc_cp_offset_t offset) 58 | #ifndef JCVM_ARRAY_SIZE_CHECK 59 | noexcept 60 | #endif /* JCVM_ARRAY_SIZE_CHECK */ 61 | ; 62 | 63 | /// Converting a union cap_class_ref to either jc_cap_class or 64 | /// jc_cap_interface structure. 65 | std::pair 66 | resolveClassref(const jc_cap_class_ref classref) 67 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 68 | noexcept 69 | #endif 70 | ; 71 | 72 | /// Convert constant pool offset to jc_class_ref 73 | const jc_cap_class_ref getClassRef(const jc_cp_offset_t offset) 74 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 75 | noexcept 76 | #endif 77 | ; 78 | 79 | // Convert class index to jc_cap_class_info * 80 | const jc_cap_class_info * 81 | getClassFromClassIndex(const jclass_index_t claz_index) 82 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 83 | noexcept 84 | #endif 85 | ; 86 | 87 | /// Convert class index to internal class ref 88 | const jc_cap_class_ref 89 | getClassRefFromClassIndex(const jclass_index_t claz_index); 90 | 91 | /// Convert constant pool offset to struct jc_cap_virtual_method_ref_info 92 | const jc_cap_instance_field_ref_info 93 | getInstanceFieldRef(const jc_cp_offset_t offset) 94 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 95 | noexcept 96 | #endif 97 | ; 98 | 99 | /// Convert constant pool offset to struct jc_cap_virtual_method_ref_info 100 | const jc_cap_virtual_method_ref_info 101 | getVirtualMethodRef(const jc_cp_offset_t offset) 102 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 103 | noexcept 104 | #endif 105 | ; 106 | 107 | /// Convert constant pool offset to struct jc_cap_super_method_ref_info 108 | const jc_cap_super_method_ref_info 109 | getSuperMethodRef(const jc_cp_offset_t offset) 110 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 111 | noexcept 112 | #endif 113 | ; 114 | 115 | /// Convert jc_class_ref to struct jc_cap_interface structure. 116 | std::pair 117 | classref2class(const jc_cap_class_ref classref) 118 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 119 | noexcept 120 | #endif 121 | ; 122 | /// Convert jc_class_ref to struct jc_cap_interface structure. 123 | std::pair 124 | classref2interface(const jc_cap_class_ref classref) 125 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 126 | noexcept 127 | #endif 128 | ; 129 | 130 | const jc_cap_static_field_ref_info 131 | getStaticFieldRefInfo(const jc_cp_offset_t offset) 132 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 133 | noexcept 134 | #endif 135 | ; 136 | 137 | const jc_cap_static_method_ref_info 138 | getStaticMethodRefInfo(const jc_cp_offset_t offset) 139 | #if !defined(JCVM_ARRAY_SIZE_CHECK) && !defined(JCVM_DYNAMIC_CHECKS_CAP) 140 | noexcept 141 | #endif 142 | ; 143 | }; 144 | 145 | } // namespace jcvm 146 | 147 | #endif /* _JC_CONSTANT_POOL_HPP */ 148 | -------------------------------------------------------------------------------- /src/jc_bytecodes/bc_return.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "../debug.hpp" 29 | #include "../stack.hpp" 30 | #include "bytecodes.hpp" 31 | 32 | namespace jcvm { 33 | 34 | /** 35 | * Return reference from method 36 | * 37 | * Format: 38 | * areturn 39 | * 40 | * Forms: 41 | * areturn = 119 (0x77) 42 | * 43 | * Stack: 44 | * ..., objectref -> [empty] 45 | * 46 | * Description: 47 | * 48 | * The objectref must be of type reference. The objectref is popped from 49 | * the operand stack of the current frame (§3.5 Frames) and pushed onto the 50 | * operand stack of the frame of the invoker. Any other values on the 51 | * operand stack of the current method are discarded. 52 | * 53 | * The virtual machine then reinstates the frame of the invoker and 54 | * returns control to the invoker. 55 | * 56 | */ 57 | void Bytecodes::bc_areturn() { 58 | jref_t returned_value; 59 | Stack &stack = this->context.getStack(); 60 | 61 | TRACE_JCVM_DEBUG("ARETURN"); 62 | 63 | returned_value = stack.pop_Reference(); 64 | 65 | stack.pop_Frame(); 66 | context.backToPreviousPackageID(); 67 | 68 | stack.push_Reference(returned_value); 69 | 70 | return; 71 | } 72 | 73 | /** 74 | * Return short from method 75 | * 76 | * Format: 77 | * sreturn 78 | * 79 | * Forms: 80 | * sreturn = 120 (0x78) 81 | * 82 | * Stack: 83 | * ..., value -> [empty] 84 | * 85 | * Description: 86 | * 87 | * The value must be of type short. It is popped from the operand stack of 88 | * the current frame (§3.5 Frames) and pushed onto the operand stack of 89 | * the frame of the invoker. Any other values on the operand stack of the 90 | * current method are discarded. 91 | * 92 | * The virtual machine then reinstates the frame of the invoker and 93 | * returns control to the invoker. 94 | * 95 | */ 96 | void Bytecodes::bc_sreturn() { 97 | jshort_t returned_value; 98 | Stack &stack = this->context.getStack(); 99 | 100 | TRACE_JCVM_DEBUG("SRETURN"); 101 | 102 | returned_value = stack.pop_Short(); 103 | 104 | stack.pop_Frame(); 105 | context.backToPreviousPackageID(); 106 | 107 | stack.push_Short(returned_value); 108 | 109 | return; 110 | } 111 | 112 | #ifdef JCVM_INT_SUPPORTED 113 | /** 114 | * Return int from method 115 | * 116 | * Format: 117 | * ireturn 118 | * 119 | * Forms: 120 | * ireturn = 121 (0x79) 121 | * 122 | * Stack: 123 | * ..., value.word1, value.word2 -> [empty] 124 | * 125 | * Description: 126 | * 127 | * The value must be of type int. It is popped from the operand stack of 128 | * the current frame (§3.5 Frames) and pushed onto the operand stack of 129 | * the frame of the invoker. Any other values on the operand stack of the 130 | * current method are discarded. 131 | * 132 | * The virtual machine then reinstates the frame of the invoker and 133 | * returns control to the invoker. 134 | * 135 | * Notes: 136 | * 137 | * If a virtual machine does not support the int data type, the ireturn 138 | * instruction will not be available. 139 | * 140 | */ 141 | void Bytecodes::bc_ireturn() { 142 | jint_t returned_value; 143 | Stack &stack = this->context.getStack(); 144 | 145 | TRACE_JCVM_DEBUG("IRETURN"); 146 | 147 | returned_value = stack.pop_Int(); 148 | 149 | stack.pop_Frame(); 150 | context.backToPreviousPackageID(); 151 | 152 | stack.push_Int(returned_value); 153 | 154 | return; 155 | } 156 | #endif /* JCVM_INT_SUPPORTED */ 157 | 158 | /** 159 | * Return void from method 160 | * 161 | * Format: 162 | * return 163 | * 164 | * Forms: 165 | * return = 122 (0x7a) 166 | * 167 | * Stack: 168 | * ... -> [empty] 169 | * 170 | * Description: 171 | * 172 | * Any values on the operand stack of the current method are discarded. 173 | * The virtual machine then reinstates the frame of the invoker and 174 | * returns control to the invoker. 175 | * 176 | */ 177 | void Bytecodes::bc_return() { 178 | Stack &stack = this->context.getStack(); 179 | 180 | TRACE_JCVM_DEBUG("RETURN"); 181 | 182 | stack.pop_Frame(); 183 | context.backToPreviousPackageID(); 184 | 185 | return; 186 | } 187 | } // namespace jcvm 188 | -------------------------------------------------------------------------------- /stm32f401xe.ld: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASHLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 16K 4 | FLASHCODE (rx) : ORIGIN = 0x08060000, LENGTH = 128K 5 | RAM (rw) : ORIGIN = 0x20000000, LENGTH = 96K 6 | } 7 | 8 | STACK_SIZE = 0x800; 9 | HEAP_SIZE = 0x800; 10 | SHARED_RW_SIZE = 0x1000; 11 | ARGBUF_SIZE = 0x400; 12 | 13 | ENTRY(Reset_Handler) 14 | 15 | SECTIONS 16 | { 17 | /***************************************************\ 18 | * ISR vector that must be kept at byte 0 in flash * 19 | \***************************************************/ 20 | .flashloader : 21 | { 22 | KEEP(*(.isr_vector)) 23 | } > FLASHLOADER 24 | 25 | /*************\ 26 | * Main code * 27 | \*************/ 28 | .text : 29 | { 30 | *(.text*) 31 | 32 | KEEP(*(.init)) 33 | KEEP(*(.fini)) 34 | 35 | *(.rodata*) 36 | } > FLASHCODE 37 | 38 | /****************************************************\ 39 | * Unwinding metadata (for future linking with C++) * 40 | \****************************************************/ 41 | .ARM.extab : 42 | { 43 | *(.ARM.extab* .gnu.linkonce.armextab.*) 44 | } > FLASHCODE 45 | .ARM.exidx : 46 | { 47 | __exidx_start = .; 48 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 49 | } > FLASHCODE 50 | __exidx_end = .; 51 | dottext_end_addr = .; 52 | 53 | /*********************\ 54 | * OS stack and heap * 55 | \*********************/ 56 | .stack_and_heap : 57 | { 58 | stack_lowest = .; 59 | . += STACK_SIZE; 60 | stack_highest = .; 61 | _estack = .; 62 | heap_begin = .; 63 | . += HEAP_SIZE; 64 | heap_end = .; 65 | heap_size = heap_end - heap_begin; 66 | } > RAM 67 | 68 | mpu_ospriv_start = ADDR(.stack_and_heap); 69 | mpu_ospriv_size = SIZEOF(.stack_and_heap); 70 | ASSERT(mpu_ospriv_size == (1 << LOG2CEIL(mpu_ospriv_size)), 71 | "OS-private region must be sized a power of two") 72 | /* Somehow without these lines, ld considers start & (size - 1) as a symbol 73 | * relocated on top of RAM, hence returning 74 | * ORIGIN(RAM) + (start - ORIGIN(RAM)) & (size - 1), which is not what is 75 | * expected. Adding these temporaries seems to make things work. 76 | */ 77 | mpu_ospriv_mask = mpu_ospriv_size - 1; 78 | mpu_ospriv_shouldbezero = mpu_ospriv_start & mpu_ospriv_mask; 79 | ASSERT(mpu_ospriv_shouldbezero == 0, 80 | "OS-private region must be naturally aligned") 81 | 82 | /**************************************\ 83 | * Shared buffer for argument passing * 84 | \**************************************/ 85 | .shared_rw : 86 | { 87 | KEEP(*(.data._impure_ptr*)) 88 | KEEP(*(*eh_globals)) 89 | KEEP(*(*__terminate_handler*)) 90 | KEEP(*(*__unexpected_handler*)) 91 | KEEP(*(*emergency_pool*)) 92 | mpu_shared_rw_start_to_clean = .; 93 | . += SHARED_RW_SIZE - mpu_shared_rw_start_to_clean ; 94 | } > RAM 95 | 96 | mpu_shared_rw_start = ADDR(.shared_rw); 97 | mpu_shared_rw_size = SIZEOF(.shared_rw); 98 | ASSERT(mpu_shared_rw_size == (1 << LOG2CEIL(mpu_shared_rw_size)), 99 | "Shared-RW must be sized a power of two") 100 | 101 | /* See mpu_ospriv comment */ 102 | mpu_shared_rw_mask = mpu_shared_rw_size - 1; 103 | mpu_shared_rw_shouldbezero = mpu_shared_rw_start & mpu_shared_rw_mask; 104 | ASSERT(mpu_shared_rw_shouldbezero == 0, 105 | "Shared-RW is not naturally aligned") 106 | 107 | mpu_argbuf_size = ARGBUF_SIZE; 108 | 109 | /****************************\ 110 | * Data to be copied in RAM * 111 | \****************************/ 112 | .shared_ro : AT (dottext_end_addr) 113 | { 114 | *(.shared_ro*) 115 | } 116 | 117 | mpu_shared_ro_start = ADDR(.shared_ro); 118 | mpu_shared_ro_filled_size = SIZEOF(.shared_ro); 119 | mpu_shared_ro_size_exact = 1 << LOG2CEIL(mpu_shared_ro_filled_size); 120 | mpu_shared_ro_size = MAX(32, mpu_shared_ro_size_exact); 121 | /* See mpu_ospriv comment */ 122 | mpu_shared_ro_mask = mpu_shared_ro_size - 1; 123 | mpu_shared_ro_shouldbezero = mpu_shared_ro_start & mpu_shared_ro_mask; 124 | ASSERT(mpu_shared_ro_shouldbezero == 0, 125 | "Shared-RO is not naturally aligned") 126 | 127 | .shared_ro_fill : 128 | { 129 | . += mpu_shared_ro_size - mpu_shared_ro_filled_size; 130 | } > RAM 131 | 132 | .data : 133 | { 134 | _sdata = .; /* Used by startup code by stm */ 135 | 136 | *(.data*) 137 | 138 | . = ALIGN(4); 139 | _edata = .; /* Used by startup code by stm */ 140 | } > RAM 141 | 142 | _sidata = LOADADDR(.data); /* Used by startup code by stm */ 143 | 144 | .bss : 145 | { 146 | . = ALIGN(4); 147 | _sbss = .; /* Used by startup code by stm */ 148 | 149 | *(.bss*) 150 | *(COMMON) 151 | 152 | . = ALIGN(4); 153 | _ebss = .; /* Used by startup code by stm */ 154 | } > RAM 155 | 156 | 157 | /*******************************\ 158 | * Reserved space for contexts * 159 | \*******************************/ 160 | mpu_contexts_start = .; 161 | mpu_contexts_already_filled = mpu_contexts_start - ORIGIN(RAM); 162 | .reserved_contexts : 163 | { 164 | . = LENGTH(RAM) - mpu_contexts_already_filled; 165 | } 166 | mpu_contexts_size = . - mpu_contexts_start; 167 | } 168 | -------------------------------------------------------------------------------- /src/heap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "heap.hpp" 29 | #include "jc_handlers/jc_cp.hpp" 30 | #include "jc_types/jc_array.hpp" 31 | 32 | #include 33 | 34 | namespace jcvm { 35 | 36 | /** 37 | * Default constructor. 38 | * 39 | * @param[owner] Applet ID owner 40 | */ 41 | Heap::Heap(const japplet_ID_t owner) noexcept : owner(owner) {} 42 | 43 | /* 44 | * Getting the applet ID owner 45 | * 46 | * @return heap owner. 47 | */ 48 | japplet_ID_t Heap::getOwner() const { return this->owner; } 49 | 50 | /* 51 | * Creating an array of primitive in the heap. 52 | * 53 | * @param[length] new array length 54 | * @param[type] new array type 55 | * 56 | * @return reference value. 57 | */ 58 | jref_t Heap::addArray(const uint16_t nb_entry, const jc_array_type type) { 59 | jref_t ref; 60 | 61 | // Creating and adding new array in the heap. 62 | this->arrays.push_back(std::make_shared(*this, nb_entry, type)); 63 | 64 | ref.setAsArray(true); 65 | ref.setOffset(this->arrays.size()); 66 | 67 | return ref; 68 | } 69 | /* 70 | * Creating an array in the heap. 71 | * 72 | * @param[length] new array length 73 | * @param[type] new array type 74 | * @param[array_reference_type] type of the references. 75 | * 76 | * @return reference value. 77 | */ 78 | jref_t Heap::addArray(const uint16_t nb_entry, const jc_array_type type, 79 | const jc_cp_offset_t reference_type) { 80 | jref_t ref; 81 | 82 | // Creating and adding new array in the heap. 83 | this->arrays.push_back( 84 | std::make_shared(*this, nb_entry, type, reference_type)); 85 | 86 | ref.setAsArray(true); 87 | ref.setOffset(this->arrays.size()); 88 | 89 | return ref; 90 | } 91 | 92 | /* 93 | * Creating add an array in the heap. 94 | * 95 | * @param[array] array to add 96 | * 97 | * @return reference value. 98 | */ 99 | jref_t Heap::addArray(JC_Array array) { 100 | jref_t ref; 101 | 102 | // Adding new array in the heap. 103 | this->arrays.push_back(std::make_shared(array)); 104 | 105 | ref.setAsArray(true); 106 | ref.setOffset(this->arrays.size()); 107 | 108 | return ref; 109 | } 110 | 111 | /* 112 | * Adding new instance in the transient heap. 113 | * 114 | * @param[PackageID] package type ID 115 | * @param[isPersistent] is a persistant 116 | * @param[instantiated_class] instance type to add. 117 | */ 118 | jref_t Heap::addInstance(const jpackage_ID_t packageID, 119 | const jclass_index_t instantiated_class) { 120 | jref_t ref; 121 | 122 | // Creating and adding new instance in the heap. 123 | this->instances.push_back( 124 | std::make_shared(*this, packageID, instantiated_class)); 125 | 126 | ref.setAsArray(false); 127 | ref.setOffset(this->instances.size()); 128 | 129 | return ref; 130 | } 131 | 132 | /* 133 | * Adding an instance in the transient heap. 134 | * 135 | * @param[instance] pointer to the new instance to add. 136 | */ 137 | jref_t Heap::addInstance(JC_Instance instance) { 138 | jref_t ref; 139 | 140 | // Creating and adding new instance in the heap. 141 | this->instances.push_back(std::make_shared(instance)); 142 | 143 | ref.setAsArray(false); 144 | ref.setOffset(this->instances.size()); 145 | 146 | return ref; 147 | } 148 | 149 | /* 150 | * Getting array from heap. 151 | * 152 | * @param[objectref] reference to the objectref to get. 153 | */ 154 | std::shared_ptr Heap::getArray(const jref_t objectref) 155 | #ifndef JCVM_SECURE_HEAP_ACCESS 156 | noexcept 157 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 158 | { 159 | 160 | if (objectref.isNullPointer()) { 161 | throw Exceptions::NullPointerException; 162 | } 163 | 164 | #ifdef JCVM_SECURE_HEAP_ACCESS 165 | 166 | if (!objectref.isArray()) { 167 | throw Exceptions::SecurityException; 168 | } 169 | 170 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 171 | 172 | return this->arrays.at(objectref.getOffset() - 1); 173 | } 174 | 175 | /* 176 | * Getting instance from heap. 177 | * 178 | * @param[objectref] reference to the objectref to get. 179 | */ 180 | std::shared_ptr Heap::getInstance(const jref_t objectref) 181 | #ifndef JCVM_SECURE_HEAP_ACCESS 182 | noexcept 183 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 184 | { 185 | 186 | if (objectref.isNullPointer()) { 187 | throw Exceptions::NullPointerException; 188 | } 189 | 190 | #ifdef JCVM_SECURE_HEAP_ACCESS 191 | 192 | if (objectref.isArray()) { 193 | throw Exceptions::SecurityException; 194 | } 195 | 196 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 197 | 198 | return this->instances.at(objectref.getOffset() - 1); 199 | } 200 | 201 | } // namespace jcvm 202 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_method.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_METHOD_HPP 29 | #define _JC_CAP_METHOD_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_exception_handler_info { 38 | uint16_t start_offset; /* Offset of where the try-statement starts */ 39 | #ifdef NVM_BIG_ENDIAN 40 | uint16_t stop_bit : 1; /* 0: there is/are another exception handler for the 41 | * try-statement */ 42 | uint16_t active_length : 15; /* Length in byte of the try-statement */ 43 | #else /* !NVM_BIG_ENDIAN */ 44 | uint16_t active_length : 15; /* Length in byte of the try-statement */ 45 | uint16_t stop_bit : 1; /* 0: there is/are another exception handler for the 46 | * try-statement */ 47 | #endif /* NVM_BIG_ENDIAN */ 48 | uint16_t handler_offset; /* Start offset of the catch/finally-statement */ 49 | uint16_t catch_type_index; /* !=0 => type of the exception to catch */ 50 | }; 51 | 52 | struct __attribute__((__packed__)) jc_cap_method_header_info { 53 | #ifdef NVM_BIG_ENDIAN 54 | uint8_t flags : 4; /* Method header flag */ 55 | uint8_t max_stack : 4; /* Max operand stack word for the method */ 56 | #else /* !NVM_BIG_ENDIAN */ 57 | uint8_t max_stack : 4; /* Max operand stack word for the method */ 58 | uint8_t flags : 4; /* Method header flag */ 59 | #endif /* NVM_BIG_ENDIAN */ 60 | 61 | #ifdef NVM_BIG_ENDIAN 62 | uint8_t nargs : 4; /* Method arguments word */ 63 | uint8_t max_locals : 4; /* Number of method local variable word */ 64 | #else /* !NVM_BIG_ENDIAN */ 65 | uint8_t max_locals : 4; /* Number of method local variable word */ 66 | uint8_t nargs : 4; /* Method arguments word */ 67 | #endif /* NVM_BIG_ENDIAN */ 68 | }; 69 | 70 | struct __attribute__((__packed__)) jc_cap_extended_method_header_info { 71 | #ifdef NVM_BIG_ENDIAN 72 | uint8_t flags : 4; /* Method header flags */ 73 | uint8_t padding : 4; /* padding, must be equal to 0 */ 74 | #else /* !NVM_BIG_ENDIAN */ 75 | uint8_t padding : 4; /* padding, must be equal to 0 */ 76 | uint8_t flags : 4; /* Method header flags */ 77 | #endif /* NVM_BIG_ENDIAN */ 78 | uint8_t max_stack; /* Max operand stack word for the method */ 79 | uint8_t nargs; /* Method arguments word */ 80 | uint8_t max_locals; /* Number of method local variable word */ 81 | }; 82 | 83 | // #define JC_CAP_FLAGS_ACC_INTERFACE (uint8_t) 0x8 84 | // #define JC_CAP_FLAGS_ACC_SHAREABLE (uint8_t) 0x4 85 | // #define JC_CAP_FLAGS_ACC_REMOTE (uint8_t) 0x2 86 | // #define JC_CAP_FLAGS_ACC_DEFAULT (uint8_t) 0x0 87 | 88 | #define JC_CAP_METHOD_HEADER_FLAGS_ACC_EXTENDED (uint8_t)0x8 89 | #define JC_CAP_METHOD_HEADER_FLAGS_ACC_ABSTRACT (uint8_t)0x4 90 | 91 | struct __attribute__((__packed__)) jc_cap_method_info { 92 | struct jc_cap_method_header_info method_header; // Method header 93 | uint8_t bytecodes[]; /* Method bytecodes */ 94 | }; 95 | 96 | struct __attribute__((__packed__)) jc_cap_extended_method_info { 97 | struct jc_cap_extended_method_header_info method_header; // Method header 98 | uint8_t bytecodes[]; /* Method bytecodes */ 99 | }; 100 | 101 | #define IS_EXTENDED_METHOD(method_info) \ 102 | (((struct jc_cap_method_info *)method_info)->method_header.flags & \ 103 | JC_CAP_METHOD_HEADER_FLAGS_ACC_EXTENDED) 104 | #define IS_ABSTRACT_METHOD(method_info) \ 105 | (((struct jc_cap_method_info *)method_info)->method_header.flags & \ 106 | JC_CAP_METHOD_HEADER_FLAGS_ACC_ABSTRACT) 107 | 108 | struct __attribute__((__packed__)) jc_cap_method_component { 109 | uint8_t tag; /* Component tag: COMPONENT_Method (7) */ 110 | uint16_t size; /* Component size */ 111 | uint8_t handler_count; /* Number of entries in the exception_handlers */ 112 | uint8_t data[]; 113 | // { 114 | // jc_cap_exception_handler_info exception_handlers [/* handler_count */]; 115 | // uint8_t methods[]; 116 | // } 117 | 118 | const JCVMArray 119 | exception_handlers() const noexcept { 120 | return JCVMArray( 121 | handler_count, (const jc_cap_exception_handler_info *)data); 122 | } 123 | 124 | const JCVMArray methods() const noexcept { 125 | return JCVMArray( 126 | (size - (handler_count * sizeof(jc_cap_exception_handler_info))), 127 | (uint8_t *)(data + 128 | handler_count * sizeof(jc_cap_exception_handler_info))); 129 | } 130 | }; 131 | 132 | } // namespace jcvm 133 | 134 | #endif /* _JC_CAP_METHOD_HPP */ 135 | -------------------------------------------------------------------------------- /src/main_pc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifdef PC_VERSION 29 | 30 | #include "debug.hpp" 31 | #include "ffi.h" 32 | #include "interpretor.hpp" 33 | #include "jc_config.h" 34 | #include "jni.hpp" 35 | #include "types.hpp" 36 | 37 | #ifdef DEBUG 38 | #include 39 | #include 40 | #endif /* DEBUG */ 41 | 42 | #include "jc_handlers/flashmemory.hpp" 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | bool isSaving = false; 51 | uint8_t *flash = nullptr; 52 | uint32_t flash_length = 0; 53 | std::string flash_filename; 54 | 55 | int main_pc(int argc, char *argv[]) { 56 | 57 | /** Define and parse the program options 58 | */ 59 | boost::program_options::options_description desc("Options"); 60 | desc.add_options() 61 | #ifdef DEBUG 62 | ("help,h", "Print help messages") 63 | #endif /* DEBUG */ 64 | ("memory,m", 65 | boost::program_options::value(&flash_filename) 66 | ->required() 67 | ->value_name("MEMORY_FILENAME"), 68 | "Flash Memory")("save,s", "Save modifications on MEMORY_FILENAME"); 69 | 70 | boost::program_options::variables_map parameters; 71 | 72 | try { 73 | boost::program_options::store( 74 | boost::program_options::parse_command_line(argc, argv, desc), 75 | parameters); // can throw 76 | 77 | #ifdef DEBUG 78 | 79 | /** 80 | * --help option 81 | */ 82 | if (parameters.count("help")) { 83 | std::cout 84 | << "USAGE: " << argv[0] << " [OPTION] -m MEMORY_FILENAME" << std::endl 85 | << std::endl 86 | << "CHOUPI is a secure Java Card open-source implementation." 87 | << std::endl 88 | << "This proof of concept is powered by ANSSI (www.ssi.gouv.fr)." 89 | << std::endl 90 | << "Last update: " << __DATE__ << " - " << __TIME__ << std::endl 91 | << std::endl 92 | << desc << std::endl; 93 | return EXIT_SUCCESS; 94 | } 95 | 96 | #endif /* DEBUG */ 97 | 98 | boost::program_options::notify(parameters); 99 | 100 | } catch (boost::program_options::error &e) { 101 | #ifdef DEBUG 102 | std::cerr << "ERROR: " << e.what() << std::endl 103 | << std::endl 104 | << "USAGE: " << argv[0] << " [OPTION] -m MEMORY_FILENAME" 105 | << std::endl 106 | << std::endl 107 | << "CHOUPI is a secure Java Card open-source implementation." 108 | << std::endl 109 | << "This proof of concept is powered by ANSSI (www.ssi.gouv.fr)." 110 | << std::endl 111 | << "Last update: " << __DATE__ << " - " << __TIME__ << std::endl 112 | << std::endl 113 | << desc << std::endl; 114 | #endif /* DEBUG */ 115 | return EXIT_FAILURE; 116 | } 117 | 118 | #ifdef DEBUG 119 | std::cout << "Welcome to CHOUPI implementation!" << std::endl 120 | << "CHOUPI is a secure Java Card open-source implementation." 121 | << std::endl 122 | << "This proof of concept is powered by ANSSI (www.ssi.gouv.fr)." 123 | << std::endl 124 | << "Last update: " << __DATE__ << " - " << __TIME__ << std::endl 125 | << std::endl 126 | << "CHOUPI is starting :)" << std::endl 127 | << std::endl; 128 | #endif /* DEBUG */ 129 | 130 | auto file_memory_in = std::ifstream(flash_filename, std::ifstream::binary); 131 | flash = flash_pointer(); 132 | 133 | if (file_memory_in.is_open()) { 134 | uint8_t *last = std::copy(std::istreambuf_iterator(file_memory_in), 135 | std::istreambuf_iterator(), flash); 136 | flash_length = (last - flash); 137 | 138 | #ifdef DEBUG 139 | TRACE_JCVM_ERR("Flash length = %u Byte", flash_length); 140 | #endif /* DEBUG */ 141 | } else { 142 | #ifdef DEBUG 143 | TRACE_JCVM_ERR("ERROR: Unable to open %s", flash_filename); 144 | #endif /* DEBUG */ 145 | return EXIT_FAILURE; 146 | } 147 | 148 | file_memory_in.close(); 149 | 150 | isSaving = parameters.count("save"); 151 | 152 | // running emulator 153 | run_emulator(); 154 | 155 | return 0; 156 | } 157 | 158 | #ifdef __cplusplus 159 | extern "C" { 160 | #endif 161 | 162 | // The runtime_main function is called in the context 0. 163 | int starting_jcre() { 164 | 165 | TRACE_JCVM_DEBUG("Starting JCRE"); 166 | 167 | // Call GP applet => main security domain 168 | uint32_t arg = (STARTING_JAVACARD_PACKAGE << 16) | 169 | (STARTING_JAVACARD_CLASS << 8) | (STARTING_JAVACARD_METHOD); 170 | remote_call(2, arg, 0); 171 | 172 | if (isSaving) { 173 | TRACE_JCVM_DEBUG("Saving memory in FLASH_MEMORY file"); 174 | 175 | auto flash_memory_out = 176 | std::ofstream(flash_filename, std::ofstream::binary); 177 | std::ostream_iterator output(flash_memory_out); 178 | std::copy(flash, flash + flash_length, output); 179 | flash_memory_out.close(); 180 | } 181 | 182 | return 0; 183 | } 184 | #ifdef __cplusplus 185 | } 186 | #endif 187 | 188 | #endif /* PC_VERSION */ 189 | -------------------------------------------------------------------------------- /src/frame.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #include "frame.hpp" 29 | 30 | namespace jcvm { 31 | /** 32 | * Pushing a value on the operand stack 33 | * 34 | * @param[value] the byte value to push. 35 | */ 36 | void Frame::push_Value(const jword_t value) 37 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 38 | noexcept 39 | #endif 40 | { 41 | #ifdef JCRE_STACK_OVERFLOW_PROTECTION 42 | 43 | if (this->tos >= this->eos) { 44 | // Stack overflow detected!!!! 45 | throw Exceptions::StackOverflowException; 46 | } 47 | 48 | #endif /* JCRE_STACK_OVERFLOW_PROTECTION */ 49 | 50 | *(this->tos) = value; 51 | this->tos++; // a value is pushed 52 | } 53 | 54 | /** 55 | * Popping a value from the stack 56 | * 57 | * @return the top of stack element as a short value. 58 | */ 59 | jword_t Frame::pop_Value() 60 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 61 | noexcept 62 | #endif 63 | { 64 | this->tos--; 65 | 66 | #ifdef JCRE_STACK_OVERFLOW_PROTECTION 67 | 68 | if (this->tos < this->op) { 69 | // Stack underflow detected!!!! 70 | throw Exceptions::StackUnderflowException; 71 | } 72 | 73 | #endif /* JCRE_STACK_OVERFLOW_PROTECTION */ 74 | 75 | return *(this->tos); 76 | } 77 | 78 | /** 79 | * Reading a local variable as a value 80 | * 81 | * @return the local variable value at 'local_number' position. 82 | */ 83 | jword_t Frame::readLocal_Value(const uint8_t local_number) 84 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 85 | noexcept 86 | #endif 87 | { 88 | jword_t *local = (jword_t *)(this->fp + local_number); 89 | #ifdef JCRE_STACK_OVERFLOW_PROTECTION 90 | 91 | if (local >= this->op) { 92 | // Stack overflow detected!!!! 93 | throw Exceptions::StackOverflowException; 94 | } 95 | 96 | #endif /* JCRE_STACK_OVERFLOW_PROTECTION */ 97 | 98 | return *local; 99 | } 100 | 101 | /** 102 | * Writing to local variable 103 | * 104 | * @param [value] value to save. 105 | * @param [local_number] the local variable position. 106 | */ 107 | void Frame::writeLocal_Value(const uint8_t local_number, const int16_t value) 108 | #ifndef JCRE_STACK_OVERFLOW_PROTECTION 109 | noexcept 110 | #endif 111 | { 112 | jword_t *local = this->fp + local_number; 113 | 114 | #ifdef JCRE_STACK_OVERFLOW_PROTECTION 115 | 116 | if (local >= this->op) { 117 | // Stack overflow detected!!!! 118 | throw Exceptions::StackOverflowException; 119 | } 120 | 121 | #endif /* JCRE_STACK_OVERFLOW_PROTECTION */ 122 | 123 | *(local) = (jword_t)value; 124 | } 125 | 126 | /** 127 | * Return frame base pointer. 128 | * 129 | * @return the current frame base pointer. 130 | */ 131 | jword_t *Frame::getFP() const noexcept { return this->fp; } 132 | 133 | /** 134 | * Return operand stack base pointer. 135 | * 136 | * @return the current operand stack base pointer. 137 | */ 138 | jword_t *Frame::getOP() const noexcept { return this->op; } 139 | 140 | /** 141 | * Return top of operand stack. 142 | * 143 | * @return the current top of operand stack. 144 | */ 145 | jword_t *Frame::getTOS() const noexcept { return this->tos; } 146 | 147 | /** 148 | * Return end of operand stack. 149 | * 150 | * @return the current end of operand stack. 151 | */ 152 | jword_t *Frame::getEOS() const noexcept { return this->eos; } 153 | 154 | /** 155 | * Return method program counter. 156 | * 157 | * @return the current method program counter. 158 | */ 159 | pc_t &Frame::getPC() noexcept { return this->pc; } 160 | 161 | /** 162 | * Set frame base pointer. 163 | * 164 | * @param[fp] the new frame base pointer. 165 | */ 166 | void Frame::setFP(jword_t *fp) noexcept { this->fp = fp; } 167 | 168 | /** 169 | * Set operand stack base pointer. 170 | * 171 | * @param[op] the new operand stack base pointer. 172 | */ 173 | void Frame::setOP(jword_t *op) noexcept { this->op = op; } 174 | 175 | /** 176 | * Set top of operand stack pointer. 177 | * 178 | * @param[tos] the new top of operand stack pointer. 179 | */ 180 | void Frame::setTOS(jword_t *tos) noexcept { this->tos = tos; } 181 | 182 | /** 183 | * Set end of operand stack pointer. 184 | * 185 | * @param[eos] the new end of operand stack pointer. 186 | */ 187 | void Frame::setEOS(jword_t *eos) noexcept { this->eos = eos; } 188 | 189 | /** 190 | * Set method program counter pointer. 191 | * 192 | * @param[pc] the new method program counter pointer. 193 | */ 194 | void Frame::setPC(pc_t &pc) noexcept { this->pc = pc; } 195 | 196 | /** 197 | * Save PC value for jsr instruction. 198 | * 199 | * @return the pc index. 200 | */ 201 | uint8_t Frame::savePC() noexcept { 202 | old_pc_t old_pc = {.isUsed = false, .pc = this->pc}; 203 | this->old_pcs.push_back(old_pc); 204 | return (this->old_pcs.size() - 1); 205 | } 206 | 207 | /** 208 | * Restore PC value for ret instruction. 209 | * 210 | * @param[index] where the PC is located. 211 | * @return the saved PC. 212 | */ 213 | pc_t &Frame::restorePC(const uint8_t index) 214 | #if !defined(JCVM_FIREWALL_CHECKS) && !defined(JCVM_ARRAY_SIZE_CHECK) 215 | noexcept 216 | #endif 217 | { 218 | old_pc_t &old_pc = this->old_pcs.at(index); 219 | 220 | #ifdef JCVM_FIREWALL_CHECKS 221 | 222 | if (old_pc.isUsed) { 223 | throw Exceptions::SecurityException; 224 | } 225 | 226 | #endif /* JCVM_FIREWALL_CHECKS */ 227 | 228 | old_pc.isUsed = true; 229 | return old_pc.pc; 230 | } 231 | 232 | }; // namespace jcvm 233 | -------------------------------------------------------------------------------- /src/jc_types/jc_array.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_ARRAY_HPP 29 | #define _JC_ARRAY_HPP 30 | 31 | #include "../jc_config.h" 32 | #include "../jc_handlers/flashmemory.hpp" 33 | #include "../jcvm_types/jcvmarray.hpp" 34 | #include "../types.hpp" 35 | #include "jc_array_type.hpp" 36 | #include "jc_object.hpp" 37 | #include "jref_t.hpp" 38 | 39 | #ifdef JCVM_FIREWALL_CHECKS 40 | #include "../context.hpp" 41 | #endif /* JCVM_FIREWALL_CHECKS */ 42 | 43 | namespace jcvm { 44 | 45 | /// Fast forward declation. 46 | class Context; 47 | 48 | enum ClearEvent : uint8_t { 49 | CLEAR_ON_SELECT = (uint8_t)1, 50 | CLEAR_ON_DESELECT = (uint8_t)2, 51 | None = (uint8_t)0xFF, 52 | }; 53 | 54 | class JC_Array : public JC_Object { 55 | private: 56 | /// Is a transient array? 57 | const bool isTransient; 58 | /// Array type elements. 59 | const jc_array_type type; 60 | /* In case of array of reference, the element type should be saved. 61 | * cp_offset is a 2-byte offset in the constant pool component. 62 | */ 63 | const jc_cp_offset_t reference_type; 64 | /// Data 65 | JCVMArray array; 66 | /// When to clear data 67 | ClearEvent clear; 68 | 69 | /// Get an entry size from the size type. 70 | static const uint16_t getEntrySize(const jc_array_type type); 71 | 72 | /// Compute tag value 73 | fs::Tag computeTag() const noexcept; 74 | 75 | public: 76 | /// Get an entry size from the size type. 77 | uint16_t getEntrySize() const; 78 | 79 | JC_Array(Heap &owner, const uint16_t size, const jc_array_type type, 80 | const bool isTransientArray = false); 81 | JC_Array(Heap &owner, const uint16_t size, const jc_array_type type, 82 | const jc_cp_offset_t reference_type, const bool isTransient = false); 83 | /// Constructor for static array? 84 | JC_Array(Heap &owner, const jc_array_type type, 85 | const jc_cp_offset_t reference_type, const fs::Tag &tag, 86 | const bool isTransientArray, 87 | const ClearEvent event = ClearEvent::None, 88 | const uint16_t length = 0) noexcept; 89 | 90 | /// Default destructor 91 | ~JC_Array() noexcept; 92 | 93 | /// Get array type 94 | jc_array_type getType() const noexcept; 95 | /// Get array Reference type 96 | jc_cp_offset_t getReferenceType() const 97 | #ifndef JCVM_SECURE_HEAP_ACCESS 98 | noexcept 99 | #endif /* JCVM_SECURE_HEAP_ACCESS */ 100 | ; 101 | /// Get array size 102 | uint16_t size() const; 103 | 104 | /// Fetch a byte or a boolean element from an array. 105 | jbyte_t getByteEntry(const uint16_t index) 106 | #ifndef JCVM_SECURE_HEAP_ACCESS 107 | const noexcept(noexcept(std::declval &>()[index])) 108 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 109 | ; 110 | /// Fetch a short element from an array. 111 | jshort_t getShortEntry(const uint16_t index) 112 | #ifndef JCVM_SECURE_HEAP_ACCESS 113 | const noexcept(noexcept(std::declval &>()[index])) 114 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 115 | ; 116 | #ifdef JCVM_INT_SUPPORTED 117 | /// Fetch an int element from an array. 118 | jint_t getIntEntry(const uint16_t index) 119 | #ifndef JCVM_SECURE_HEAP_ACCESS 120 | const noexcept(noexcept(std::declval &>()[index])) 121 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 122 | ; 123 | #endif /* JCVM_INT_SUPPORTED */ 124 | /// Fetch a reference element from an array. 125 | jref_t getReferenceEntry(const uint16_t index) 126 | #ifndef JCVM_SECURE_HEAP_ACCESS 127 | noexcept(noexcept(std::declval &>()[index])) 128 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 129 | ; 130 | 131 | /// Write a byte or a boolean element from an array. 132 | void setByteEntry(const uint16_t index, const jbyte_t value) 133 | #ifndef JCVM_SECURE_HEAP_ACCESS 134 | noexcept(noexcept(std::declval &>()[index])) 135 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 136 | ; 137 | /// Write a short element from an array. 138 | void setShortEntry(const uint16_t index, const jshort_t value) 139 | #ifndef JCVM_SECURE_HEAP_ACCESS 140 | noexcept(noexcept(std::declval &>()[index])) 141 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 142 | ; 143 | #ifdef JCVM_INT_SUPPORTED 144 | /// Write an int element from an array. 145 | void setIntEntry(const uint16_t index, const jint_t value) 146 | #ifndef JCVM_SECURE_HEAP_ACCESS 147 | noexcept(noexcept(std::declval &>()[index])) 148 | #endif /* !JCVM_SECURE_HEAP_ACCESS */ 149 | ; 150 | #endif /* JCVM_INT_SUPPORTED */ 151 | /// Write a reference element from an array. 152 | void setReferenceEntry(const uint16_t index, const jref_t value 153 | #ifdef JCVM_FIREWALL_CHECKS 154 | , 155 | Context &context 156 | #endif /* JCVM_FIREWALL_CHECKS */ 157 | ) 158 | #if !defined(JCVM_SECURE_HEAP_ACCESS) && !defined(JCVM_FIREWALL_CHECKS) 159 | noexcept(noexcept(std::declval &>()[index])) 160 | #endif /* !JCVM_SECURE_HEAP_ACCESS && !JCVM_FIREWALL_CHECKS */ 161 | ; 162 | 163 | /// Get a const pointer to array data 164 | const uint8_t *getData() const; 165 | 166 | /// Is a transient array 167 | const bool isTransientArray() const noexcept; 168 | 169 | /// Get clear event 170 | const ClearEvent getClearEvent() const noexcept; 171 | }; 172 | 173 | } // namespace jcvm 174 | #endif /* _JC_ARRAY_HPP */ 175 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_cp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_CONSTANT_POOL_HPP 29 | #define _JC_CAP_CONSTANT_POOL_HPP 30 | 31 | #include "../jc_utils.hpp" 32 | #include "../jcvm_types/jcvmarray.hpp" 33 | #include "../types.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_external_classref_info { 38 | uint8_t package_token; /* Token of the package in the Import component */ 39 | uint8_t class_token; /* Token of class or interface in the Import component */ 40 | }; 41 | 42 | union __attribute__((__packed__)) jc_cap_class_ref { 43 | uint16_t internal_classref; /* Class offset in the Class component */ 44 | jc_cap_external_classref_info external_classref; /* Imported class info. */ 45 | 46 | bool isExternalClassRef() const noexcept { 47 | return ((NTOHS(internal_classref) & (uint16_t)0x8000) != 0); 48 | } 49 | 50 | bool isInternalClassRef() const noexcept { 51 | return ((NTOHS(internal_classref) & (uint16_t)0x8000) == 0); 52 | } 53 | }; 54 | 55 | struct __attribute__((__packed__)) jc_cap_class_ref_info { 56 | jc_cap_class_ref class_ref; /* Reference to a class or an interface */ 57 | uint8_t padding; /* 1-byte padding */ 58 | }; 59 | 60 | struct __attribute__((__packed__)) jc_cap_instance_field_ref_info { 61 | jc_cap_class_ref class_ref; /* Reference to the instanced class/instance */ 62 | uint8_t token; /* Instance field token */ 63 | }; 64 | 65 | struct __attribute__((__packed__)) jc_cap_virtual_method_ref_info { 66 | jc_cap_class_ref class_ref; /* Class which contains the virtual method */ 67 | uint8_t token; /* Virtual method token of the referenced method */ 68 | 69 | /** 70 | * Is a package method? 71 | */ 72 | bool isPackageMethod() const { return ((token & 0x80) > 0); } 73 | 74 | /** 75 | * Is a public method? 76 | */ 77 | bool isPublicMethod() const { return ((token & 0x80) == 0); } 78 | }; 79 | 80 | struct __attribute__((__packed__)) jc_cap_super_method_ref_info { 81 | jc_cap_class_ref class_ref; /* Class which contains the super method */ 82 | uint8_t token; /* Super method token of the referenced method */ 83 | }; 84 | 85 | struct __attribute__((__packed__)) jc_cap_internal_ref { 86 | uint8_t padding; /* 1-byte padding */ 87 | uint16_t offset; /* 16-bit offset into the Static Field Image */ 88 | }; 89 | 90 | struct __attribute__((__packed__)) jc_cap_external_ref { 91 | uint8_t package_token; /* Package token in the Import Component */ 92 | uint8_t class_token; /* Class token of the reference class */ 93 | uint8_t token; /* Static field token */ 94 | }; 95 | 96 | union __attribute__((__packed__)) jc_cap_static_field_ref { 97 | jc_cap_internal_ref internal_ref; /* reference to a static field in this 98 | * package */ 99 | jc_cap_external_ref external_ref; /* reference to a static field defined 100 | * in an imported package */ 101 | }; 102 | 103 | struct __attribute__((__packed__)) jc_cap_static_field_ref_info { 104 | jc_cap_static_field_ref static_field_ref; /* Represents a reference to a 105 | * static field */ 106 | }; 107 | 108 | struct __attribute__((__packed__)) jc_cap_static_method_ref_info { 109 | union __attribute__((__packed__)) { 110 | jc_cap_internal_ref internal_ref; /* Represents a reference to a static 111 | * method defined in this package */ 112 | jc_cap_external_ref external_ref; /* represents a reference to a static 113 | * method defined in an imported 114 | * package */ 115 | } static_method_ref; 116 | }; /* Represents a reference to a static method */ 117 | 118 | #define IS_CP_EXTERNAL_REF(ref) \ 119 | ((ref.external_ref.package_token & 0x80) == 0x80) 120 | #define IS_CP_INTERNAL_REF(ref) (!IS_CP_EXTERNAL_REF(ref)) 121 | 122 | struct __attribute__((__packed__)) jc_cap_constant_pool_info { 123 | uint8_t tag; /* Constant pool entry tag */ 124 | union { // 3-Byte element 125 | jc_cap_class_ref_info class_ref_info; 126 | jc_cap_instance_field_ref_info instance_field_ref_info; 127 | jc_cap_virtual_method_ref_info virtual_method_ref_info; 128 | jc_cap_super_method_ref_info super_method_ref_info; 129 | jc_cap_static_field_ref_info static_field_ref_info; 130 | jc_cap_static_method_ref_info static_method_ref_info; 131 | } info; 132 | }; 133 | 134 | #define JC_CP_TAG_CONSTANT_CLASSREF (uint8_t)1 135 | #define JC_CP_TAG_CONSTANT_INSTANCEFIELDREF (uint8_t)2 136 | #define JC_CP_TAG_CONSTANT_VIRTUALMETHODREF (uint8_t)3 137 | #define JC_CP_TAG_CONSTANT_SUPERMETHODREF (uint8_t)4 138 | #define JC_CP_TAG_CONSTANT_STATICFIELDREF (uint8_t)5 139 | #define JC_CP_TAG_CONSTANT_STATICMETHODREF (uint8_t)6 140 | 141 | struct __attribute__((__packed__)) jc_cap_constant_pool_component { 142 | uint8_t tag; /* Tag component: COMPONENT_ConstantPool (5) */ 143 | uint16_t size; /* Component size */ 144 | uint16_t count; /* Number of constant_pool entries */ 145 | jc_cap_constant_pool_info constant_pool[/* count */]; /* constant pool 146 | * entries */ 147 | 148 | JCVMArray constantpool() const noexcept { 149 | return JCVMArray(HTONS(count), 150 | constant_pool); 151 | } 152 | }; 153 | 154 | } // namespace jcvm 155 | 156 | #endif /* _JC_CAP_CONSTANT_POOL_HPP */ 157 | -------------------------------------------------------------------------------- /src/stack.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _STACK_HPP 29 | #define _STACK_HPP 30 | 31 | #include "exceptions.hpp" 32 | #include "frame.hpp" 33 | #include "jc_config.h" 34 | #include "jc_types/jref_t.hpp" 35 | #include "types.hpp" 36 | 37 | // TODO: Move the PC to the context.hpp file (in the packagesID list) 38 | 39 | namespace jcvm { 40 | 41 | /** 42 | * Checks stack manipulated types size 43 | */ 44 | static_assert(sizeof(jbool_t) == sizeof(jbyte_t), 45 | "jbool_t class has a wrong size."); 46 | static_assert(sizeof(jbyte_t) == (sizeof(jword_t) / 2), 47 | "jbyte_t class has a wrong size."); 48 | static_assert(sizeof(jshort_t) == sizeof(jword_t), 49 | "jshort_t class has a wrong size."); 50 | #ifdef JCVM_INT_SUPPORTED 51 | static_assert(sizeof(jint_t) == (2 * sizeof(jword_t)), 52 | "jint_t class has a wrong size."); 53 | #endif /* JCVM_INT_SUPPORTED */ 54 | static_assert(sizeof(jreturnaddress_t) == sizeof(jword_t), 55 | "jint_t class has a wrong size."); 56 | static_assert(sizeof(std::declval().compact()) == sizeof(jword_t), 57 | "jref_t class has a wrong size."); 58 | 59 | class Stack { 60 | private: 61 | jword_t jc_stack[JCVM_STACK_SIZE]; 62 | List frames; 63 | 64 | public: 65 | // Pushing a new frame regarding the invoked method header. 66 | void push_Frame(const uint8_t nargs, const uint8_t max_locals, 67 | const uint8_t max_operand_stack, const uint8_t *pc) 68 | #if !defined(JCRE_STACK_OVERFLOW_PROTECTION) && !defined(JCVM_ARRAY_SIZE_CHECK) 69 | noexcept 70 | #endif 71 | ; 72 | 73 | // Popping the current frame without return value 74 | void pop_Frame(); 75 | // The stack is empty? (no pushed Java Card frame) 76 | bool empty() noexcept; 77 | 78 | // Pushing a byte to the operand stack 79 | void push_Byte(const jbyte_t value) noexcept( 80 | noexcept(std::declval().push_Value(value))); 81 | // Pushing a short to the operand the stack 82 | void push_Short(const jshort_t value) noexcept( 83 | noexcept(std::declval().push_Value(value))); 84 | // Pushing an integer to the operand the stack 85 | #ifdef JCVM_INT_SUPPORTED 86 | void push_Int(const jint_t value) noexcept( 87 | noexcept(std::declval().push_Value(value))); 88 | #endif /* JCVM_INT_SUPPORTED */ 89 | // Pushing a reference to the operand the stack 90 | void push_Reference(const jref_t value) noexcept( 91 | noexcept(std::declval().push_Value(value.compact()))); 92 | // Pushing a return address element to the operand the stack 93 | void push_ReturnAddress(const jreturnaddress_t value) noexcept( 94 | noexcept(std::declval().push_Value(value))); 95 | 96 | // Popping to the trash, an untyped element 97 | void pop() noexcept(noexcept(std::declval().pop_Value())); 98 | // Popping a byte from the stack 99 | jbyte_t pop_Byte() noexcept(noexcept(std::declval().pop_Value())); 100 | // Popping a short from the stack 101 | jshort_t pop_Short() noexcept(noexcept(std::declval().pop_Value())); 102 | #ifdef JCVM_INT_SUPPORTED 103 | // Popping an integer from the stack 104 | jint_t pop_Int() noexcept(noexcept(std::declval().pop_Value())); 105 | #endif /* JCVM_INT_SUPPORTED */ 106 | // Popping a reference from the stack 107 | jref_t 108 | pop_Reference() noexcept(noexcept(std::declval().pop_Value())); 109 | // Popping a return address element from the stack 110 | jreturnaddress_t 111 | pop_ReturnAddress() noexcept(noexcept(std::declval().pop_Value())); 112 | // Get a pushing element which as not the last pushed element. This function 113 | // returns the n-th pushed word without popped it. 114 | jref_t get_Pushed_Element(uint16_t n) 115 | #if !defined(JCRE_STACK_OVERFLOW_PROTECTION) && !defined(JCVM_ARRAY_SIZE_CHECK) 116 | noexcept 117 | #endif 118 | ; 119 | 120 | /// Reading a local variable as a short value 121 | int16_t readLocal_Short(const uint8_t local_number); 122 | // /Reading a local variable as an integer value 123 | #ifdef JCVM_INT_SUPPORTED 124 | int32_t readLocal_Int(const uint8_t local_number); 125 | #endif /* JCVM_INT_SUPPORTED */ 126 | /// Reading a local variable as a reference 127 | jref_t readLocal_Reference(const uint8_t local_number); 128 | /// Reading a local variable as a return address element 129 | jreturnaddress_t readLocal_ReturnAddress(const uint8_t local_number); 130 | 131 | /// Saving a short to a specific local variable 132 | void writeLocal_Short(const uint8_t local_number, const jshort_t value); 133 | #ifdef JCVM_INT_SUPPORTED 134 | /// Saving an integer to a specific local variable 135 | void writeLocal_Int(const uint8_t local_number, const jint_t value); 136 | #endif /* JCVM_INT_SUPPORTED */ 137 | /// Saving a reference to a specific local variable 138 | void writeLocal_Reference(const uint8_t local_number, const jref_t value); 139 | /// Saving a return address element to a specific local variable 140 | void writeLocal_ReturnAddress(const uint8_t local_number, 141 | const jreturnaddress_t value); 142 | 143 | /// Duplicate top operand stack words and insert below 144 | void dup(const uint8_t m, const uint8_t n); 145 | 146 | /// Swap top two operand stack words 147 | void swap(const uint8_t m, const uint8_t n); 148 | 149 | /// Get the current PC value 150 | pc_t &getPC(); 151 | /// Save PC value for jsr instruction 152 | uint8_t savePC() noexcept; 153 | /// Restore PC value for ret instruction 154 | pc_t &restorePC(const uint8_t index); 155 | /// Get the current frame 156 | Frame &getCurrentFrame(); 157 | }; 158 | 159 | } // namespace jcvm 160 | 161 | #endif /* _STACK_HPP */ 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CHOUPI - An open-source secure-oriented Java Card Virtual Machine 2 | 3 | ## Copyright and license 4 | 5 | Copyright (C) 2020 6 | 7 | This software is licensed under the MIT license. See [LICENSE](LICENSE) file at 8 | the root folder of the project. 9 | 10 | ## Author 11 | 12 | * Guillaume BOUFFARD () 13 | 14 | ## Description 15 | 16 | CHOUPI is a Java Card Virtual Machine security-oriented for small footprint 17 | device. Currently, this implementation provides a proof-of-concept of Java Card 18 | 3.0.5. 19 | 20 | ## Dependencies 21 | 22 | ### [Java Card & Global Platform API](https://github.com/choupi-project/javacard-api) 23 | 24 | * ant 25 | 26 | ### [Java Card RomMask generator](https://github.com/choupi-rommask/project) 27 | 28 | * maven 29 | 30 | ### [Java Card Operating System](https://github.com/choupi-project/choupi-os) 31 | 32 | * The `arm-none-eabi` toolchain 33 | * openocd 34 | * rlwrap 35 | 36 | ### Java Card Virtual Machine 37 | 38 | * Boost is required for building the computer version 39 | * CMake 40 | 41 | ## Fetching this repository 42 | 43 | To clone the repository and its dependency, you should execute the following 44 | command: 45 | 46 | ``` 47 | git clone --recurse-submodules https://github.com/choupi-project/choupi 48 | ``` 49 | 50 | ## Toolchain setup 51 | 52 | The nightly version of [Rust](https://www.rust-lang.org/) is required. To 53 | install it you should: 54 | 55 | 1. Install `rustup`: 56 | ``` sh 57 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh 58 | ``` 59 | 60 | 2. Adding rust to your `PATH` file: 61 | ``` sh 62 | source ~/.cargo/env 63 | ``` 64 | 65 | 3. Install the nightly version of the rust compiler: 66 | ```sh 67 | rustup default nightly-2020-03-10 68 | ``` 69 | 70 | To have a *ready-to-build* version of the Java Card OS. The last checked 71 | version of rust nightly compiler is `1.43.0-nightly`. 72 | 73 | 4. Install `xargo`: 74 | ``` sh 75 | cargo install xargo 76 | ``` 77 | 78 | 5. Add `rust-src` component: 79 | ``` sh 80 | rustup component add rust-src 81 | ``` 82 | 83 | 6. To build to ARM Cortex M4 board, you should run: 84 | ``` sh 85 | rustup target add thumbv7em-none-eabi 86 | ``` 87 | 88 | ## Building 89 | 90 | The Java Card Virtual Machine has two main targets: computer and embedded board. The 91 | Java Card OS computer version emulates the MPU behavior. The MPU emulation on computer blocks 92 | the usage of a debugger (but debugging works on embedded version :). 93 | 94 | ### Building options 95 | 96 | | Option | Default value | Description | 97 | |-----------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------| 98 | | `CHOUPI_TARGET_PC` | ON | Building for PC | 99 | | `CHOUPI_TARGET_STM32` | OFF | Building for STM32 board, currently only Nucleo [STM32f401](https://www.st.com/en/evaluation-tools/nucleo-f401re.html) is supported. | 100 | | `CHOUPI_ENABLE_LTO` | ON | Enable Link Time Optimization (LTO) | 101 | | `CHOUPI_OS_DEBUG` | ON | Enable OS debug output | 102 | | `CHOUPI_JCVM_DEBUG` | OFF | Enable JCVM debug output | 103 | 104 | ### CHOUPI for PC 105 | 106 | #### Building 107 | 108 | ``` sh 109 | mkdir -p build/pc 110 | cd build/pc 111 | cmake -DCHOUPI_TARGET_PC=ON -DCHOUPI_OS_DEBUG=ON -DCHOUPI_JCVM_DEBUG=ON ../../ 112 | make 113 | ``` 114 | 115 | #### Running 116 | 117 | To run the PC version of the JCVM, run `choupi` as: 118 | 119 | ``` sh 120 | ./choupi -m flash 121 | ``` 122 | 123 | The `flash` file is the initial memory state generated by the 124 | [rommask](https://github.com/choupi-project/rommask). 125 | 126 | The other options are the following: 127 | 128 | ``` sh 129 | Options: 130 | -h [ --help ] Print help messages 131 | -m [ --memory ] MEMORY_FILENAME Flash Memory 132 | -s [ --save ] Save modifications on MEMORY_FILENAME 133 | ``` 134 | 135 | #### Debugging the computer version 136 | 137 | Note that for tests, it may be hard to debug some issues, like when the child in 138 | an emulation has an unexpected behaviour at runtime that is not a panic!, as it 139 | would require a debugger, which is not possible given the emulator is already a 140 | pseudo-debugger. 141 | 142 | For this reason, sending `SIGILL` to the child process will make the emulator 143 | (ie. parent process) to make it dump core. 144 | The core dump can then be used to try to debug the issue. 145 | 146 | ### CHOUPI for STM32f401 board 147 | 148 | #### Building 149 | 150 | Currently, the only target is a Nucleo board which embeds a 151 | [STM32f401](https://www.st.com/en/evaluation-tools/nucleo-f401re.html). The 152 | OS can easily be extended to support new target. 153 | 154 | ``` sh 155 | mkdir -p build/stm32 156 | cd build/stm32 157 | cmake -DCHOUPI_TARGET_STM32=ON -DCHOUPI_OS_DEBUG=ON -DCHOUPI_JCVM_DEBUG=OFF ../../ 158 | make 159 | ``` 160 | 161 | Due to a missing of flash memory space, the STM32f401 version cannot embeds 162 | JCVM debug output. 163 | 164 | 165 | #### Loading on board 166 | 167 | Currently, the only target is ST Nucleo STM32f401. To load firmware on board, we 168 | use `rlwrap` though OpenOCD. 169 | 170 | 1. start OpenOCD in a terminal: 171 | ``` sh 172 | sudo make ocd 173 | ``` 174 | 175 | 2. in another terminal, run `rlwrap`: 176 | ``` sh 177 | sudo make load 178 | ``` 179 | 180 | As indicate, to install the firmware, you should execute: 181 | 182 | ``` sh 183 | reset halt; flash write_image erase loader.hex; flash write_image erase code.hex; flash write_image flash.hex; reset run 184 | ``` 185 | 186 | #### Access to debug messages 187 | 188 | To see the debug message, in case of the OS is built in debug mode. The 189 | [Makefile](Makefile) may be modified to built the OS in debug mode. 190 | 191 | ``` sh 192 | make screen 193 | ``` 194 | 195 | #### Debugging 196 | 197 | To running the OS on board though a debugger, `arm-none-eabi-gdb` must be 198 | install. 199 | 200 | 1. Starting openOCD in a terminal: 201 | ``` sh 202 | sudo make ocd 203 | ``` 204 | 205 | 2. Starting GDB in another terminal : 206 | ``` sh 207 | make debug 208 | ``` 209 | 210 | 3. Enjoy debugging 211 | 212 | # Roadmap 213 | 214 | For the version 1.0, CHOUPI must implement: 215 | 216 | * [ ] Java exceptions handling 217 | * [ ] Input/Output buffer (like ISO7816 buffer) 218 | * [ ] Object serialisation in Flash memory 219 | * [ ] Shareable interface, implemented in [OS](https://github.com/choupi-project/choupi-os) but not yet implemented in the 220 | VM layout 221 | * [ ] Transient objects 222 | * [ ] Atomicity 223 | * [ ] Implemented cryptographic functions 224 | -------------------------------------------------------------------------------- /src/jc_cap/jc_cap_descriptor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** The MIT License (MIT) 3 | ** 4 | ** Copyright (c) 2020, National Cybersecurity Agency of France (ANSSI) 5 | ** 6 | ** Permission is hereby granted, free of charge, to any person obtaining a copy 7 | ** of this software and associated documentation files (the "Software"), to deal 8 | ** in the Software without restriction, including without limitation the rights 9 | ** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | ** copies of the Software, and to permit persons to whom the Software is 11 | ** furnished to do so, subject to the following conditions: 12 | ** 13 | ** The above copyright notice and this permission notice shall be included in 14 | ** all copies or substantial portions of the Software. 15 | ** 16 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | ** THE SOFTWARE. 23 | ** 24 | ** Author: 25 | ** - Guillaume Bouffard 26 | */ 27 | 28 | #ifndef _JC_CAP_DESCRIPTOR_HPP 29 | #define _JC_CAP_DESCRIPTOR_HPP 30 | 31 | #include "../jcvm_types/jcvmarray.hpp" 32 | #include "../types.hpp" 33 | #include "jc_cap_cp.hpp" 34 | 35 | namespace jcvm { 36 | 37 | struct __attribute__((__packed__)) jc_cap_type_descriptor { 38 | /// Number of nibbles required to describe the type encoded in the type 39 | /// array 40 | uint8_t nibble_count; 41 | /// Encoded description of the type 42 | uint8_t type[/* (nibble_count+1) / 2 */]; 43 | }; 44 | 45 | struct __attribute__((__packed__)) jc_cap_field_descriptor_info { 46 | /// Token of this field 47 | uint8_t token; 48 | /// Describe the access permission to and properties of this field 49 | uint16_t access_flags; 50 | /// Reference to this field 51 | union { 52 | jc_cap_static_field_ref static_field; 53 | jc_cap_instance_field_ref_info instance_field; 54 | } field_ref; 55 | /// Type of this field, directly or indirectly 56 | union { 57 | /// Primitive type of the field 58 | uint16_t primitive_type; 59 | /// Represents a 15-bit offset into the type_descriptor_info structure 60 | uint16_t reference_type; 61 | } type; 62 | }; 63 | 64 | struct __attribute__((__packed__)) jc_cap_method_descriptor_info { 65 | /// Token of this method 66 | uint8_t token; 67 | /// Describe the access permission to and properties of this method 68 | uint8_t access_flags; 69 | /// Method offset in the Method component of the described method 70 | uint16_t method_offset; 71 | /// Offset into the type_descriptor_info which represents the method 72 | /// signature 73 | uint16_t type_offset; 74 | /// Represents the number of bytecodes in this method 75 | uint16_t bytecode_count; 76 | /// Represents the number of exception handlers implemented by this method 77 | uint16_t exception_handler_count; 78 | /// Represents the index to the first exception_handlers table entry in 79 | /// the method component 80 | uint16_t exception_handler_index; 81 | }; 82 | 83 | struct __attribute__((__packed__)) jc_cap_type_descriptor_info { 84 | /// Number of entries in the constant_pool_types array 85 | uint16_t constant_pool_count; 86 | uint8_t data[]; 87 | // { 88 | // /// Describes the types of the fields and methods referenced in the 89 | // /// Constant Pool Component 90 | // uint16_t constant_pool_types [ /* constant_pool_count */ ]; 91 | // /// Represents the types of fields and signatures of methods 92 | // struct jc_cap_type_descriptor type_desc []; 93 | // } 94 | 95 | const JCVMArray constant_pool_types() const noexcept { 96 | return JCVMArray(NTOHS(constant_pool_count), 97 | reinterpret_cast(data)); 98 | } 99 | 100 | const jc_cap_type_descriptor *type_desc() const noexcept { 101 | return reinterpret_cast( 102 | data + NTOHS(constant_pool_count) * sizeof(uint8_t)); 103 | } 104 | }; 105 | 106 | struct __attribute__((__packed__)) jc_cap_class_descriptor_info { 107 | /// Class or interface token 108 | uint8_t token; 109 | /// Mask of modifiers used to describe the access permission 110 | uint8_t access_flags; 111 | /// Link to the class_info in the Class component 112 | union jc_cap_class_ref this_class_ref; 113 | /// Number of entries in the interfaces array 114 | uint8_t interface_count; 115 | /// Number of entries in the fields array 116 | uint16_t field_count; 117 | /// Number of entries in the methods array 118 | uint16_t method_count; 119 | uint8_t data[/* interface_count + field_count + method_count */]; 120 | // { 121 | // /// Represents an array of interfaces implemented by this class 122 | // union jc_cap_class_ref interfaces [ /* interface_count */ ]; 123 | // /// Represents an array of field_descriptor_info structures 124 | // struct jc_cap_field_descriptor_info fields [ /* field_count */ ]; 125 | // /// Represents an array of method_descriptor_info structures 126 | // struct jc_cap_method_descriptor_info methods [ /* method_count */ ]; 127 | // } 128 | 129 | const JCVMArray interfaces() const noexcept { 130 | return JCVMArray(interface_count, 131 | (jc_cap_class_ref *)data); 132 | } 133 | 134 | const JCVMArray fields() const noexcept { 135 | return JCVMArray( 136 | NTOHS(field_count), 137 | (jc_cap_field_descriptor_info *)(data + 138 | interface_count * 139 | sizeof(union jc_cap_class_ref))); 140 | } 141 | 142 | const JCVMArray methods() const 143 | noexcept { 144 | return JCVMArray( 145 | NTOHS(method_count), 146 | (const jc_cap_method_descriptor_info 147 | *)(data + interface_count * sizeof(jc_cap_class_ref) + 148 | NTOHS(field_count) * sizeof(jc_cap_field_descriptor_info))); 149 | } 150 | }; 151 | 152 | struct __attribute__((__packed__)) jc_cap_descriptor_component { 153 | /// Component tag: COMPONENT_descriptor (11). 154 | uint8_t tag; 155 | /// Component size 156 | uint16_t size; 157 | /// Number of entries in the classes table. 158 | uint8_t class_count; 159 | uint8_t data[]; 160 | // { 161 | // /// Represented each class and interface defined in this package 162 | // struct jc_cap_class_descriptor_info classes [ /* class_count */ ]; 163 | // /// Lists field types and method signatures of the fields and methods 164 | // /// defined or referenced in this package. 165 | // struct jc_cap_type_descriptor_info types; 166 | // } 167 | 168 | const jc_cap_class_descriptor_info *classes() const noexcept { 169 | return reinterpret_cast(data); 170 | } 171 | 172 | const jc_cap_type_descriptor_info *types() const noexcept { 173 | return reinterpret_cast( 174 | data + class_count * sizeof(struct jc_cap_class_descriptor_info)); 175 | } 176 | }; 177 | 178 | } // namespace jcvm 179 | 180 | #endif /* _JC_CAP_DESCRIPTOR_HPP */ 181 | --------------------------------------------------------------------------------