OpenPGP API: A Case Study of AIDL Versioning - Android ...Feb 28, 2015 · OpenPGP API: A Case...
Transcript of OpenPGP API: A Case Study of AIDL Versioning - Android ...Feb 28, 2015 · OpenPGP API: A Case...
OpenPGP API: A Case Study of AIDL Versioning
Android Stammtisch January 2015
Dominik Schurmann
2015-01-28
$ whois
Dominik Schurmann
• Employed at Technische Universitat Braunschweig
• Network security research
• OpenPGP: Open standard for end-to-end email security
• Hobbyist Android developer• AdAway• F-Droid contributions• K-9 contributions• OpenKeychain: OpenPGP on Android
Activity Intents• Intents with Bundles• “An Intent is a messaging object you can use to request an
action from another app component.”
I n t e n t i n t e n t = new I n t e n t ( g e t A c t i v i t y ( ) , P a s s p h r a s eD i a l o gA c t i v i t y . c l a s s ) ;i n t e n t . pu tEx t ra ( P a s s p h r a s eD i a l o gA c t i v i t y .EXTRA SUBKEY ID , mSignMasterKeyId ) ;s t a r t A c t i v i t y F o r R e s u l t ( i n t e n t , REQUEST CODE PASSPHRASE) ;
@Over r idep u b l i c vo i d o nA c t i v i t y R e s u l t ( i n t requestCode , i n t r e su l tCode , I n t e n t data ) {
sw i t c h ( r eques tCode ) {ca se REQUEST CODE PASSPHRASE : {
i f ( r e s u l tCod e == A c t i v i t y .RESULT OK && data != n u l l ) {S t r i n g pa s s ph r a s e = data . g e t S t r i n gE x t r a (
P a s s p h r a s eD i a l o gA c t i v i t y .MESSAGE DATA PASSPHRASE) ;}r e t u r n ;
}d e f a u l t : {
supe r . o nA c t i v i t y R e s u l t ( requestCode , r e su l tCode , data ) ;}
}}
Broadcast Intents and BroadcastReceivers
• Send broadcast Intent from anywhere to BroadcastReceiver
• “A broadcast is a message that any app can receive.”
• Ordered Broadcasts
• Local Broadcasts
I n t e n t i = new I n t e n t ( ” org . s u f f i c i e n t l y s e c u r e . k e y cha i n .USER ACTION” ) ;s endBroadcas t ( i ) ;
p u b l i c c l a s s MyRece iver e x t end s B r oad ca s tRe c e i v e r {@Over r idep u b l i c vo i d onRece i ve ( Context contex t , I n t e n t i n t e n t ) {}
}
Service Intents
• Start service from anywhere with Intent
I n t e n t i n t e n t = new I n t e n t ( t h i s , K e y c h a i n I n t e n t S e r v i c e . c l a s s ) ;i n t e n t . s e tA c t i o n ( K e y c h a i n I n t e n t S e r v i c e .ACTION ENCRYPT) ;
// Crea te a new Messenger f o r the communicat ion backMessenger messenger = new Messenger ( s aveHand l e r ) ;i n t e n t . pu tEx t ra ( K e y c h a i n I n t e n t S e r v i c e .EXTRA MESSENGER, messenger ) ;
// s t a r t s e r v i c e w i th i n t e n ts t a r t S e r v i c e ( i n t e n t ) ;
Use Case/Requirements
OpenKeychain from git, branch development / K-9 Mail
Use Case/Requirements
• Expose API for other apps to encrypt/decrypt/sign/verifycontent
• Content can be quite large ⇒ streams!
• Real Inter-process communication with optional userinteraction
• API should be as easy as possible
• Some user interaction should be done by OpenKeychain, suchas passphrase input
This is madness!
Use Case/Requirements
• Expose API for other apps to encrypt/decrypt/sign/verifycontent
• Content can be quite large ⇒ streams!
• Real Inter-process communication with optional userinteraction
• API should be as easy as possible
• Some user interaction should be done by OpenKeychain, suchas passphrase input
This is madness!
Problems
• Activity Intents are easily exposed for other apps, but requireuser interaction
• Bundle extras are limited in size (˜1 MB)
• No streams over Broadcasts
ALOGE( ” ! ! ! FAILED BINDER TRANSACTION ! ! ! ” ) ;// Transac t i onTooLa rgeExcep t i on i s a checked excep t i on , on l y throw from c e r t a i n
methods .// FIXME : T ran sa c t i on too l a r g e i s the most common rea son f o r FAILED TRANSACTION// but i t i s not the on l y one . The B inde r d r i v e r can r e t u r n BR FAILED REPLY// f o r o t h e r r e a s on s a l s o , such as i f the t r a n s a c t i o n i s malformed or// r e f e r s to an FD tha t has been c l o s e d . We shou ld change the d r i v e r// to enab l e us to d i s t i n g u i s h t h e s e c a s e s i n the f u t u r e .
Android Interfaces
• “It allows you to define the programming interface that boththe client and service agree upon in order to communicate witheach other using interprocess communication (IPC)”
// IRemoteSe r v i c e . a i d lpackage com . example . and ro i d ;
// Dec l a r e any non−d e f a u l t t y p e s he r e w i th impor t s t a t emen t s
/∗∗ Example s e r v i c e i n t e r f a c e ∗/i n t e r f a c e IRemoteSe r v i c e {
/∗∗ Request the p r o c e s s ID o f t h i s s e r v i c e , to do e v i l t h i n g s w i th i t . ∗/i n t ge tP id ( ) ;
/∗∗ Demonstrates some b a s i c t yp e s t ha t you can use as pa ramete r s∗ and r e t u r n v a l u e s i n AIDL .∗/
vo i d ba s i cType s ( i n t an In t , l ong aLong , boo l ean aBoolean , f l o a t aF loat ,doub l e aDouble , S t r i n g aS t r i n g ) ;
}
Implementation of Interface and Service
p u b l i c c l a s s RemoteServ i ce ex t end s S e r v i c e {@Over r idep u b l i c vo i d onCreate ( ) {
supe r . onCreate ( ) ;}@Over r idep u b l i c I B i n d e r onBind ( I n t e n t i n t e n t ) {
// Return the i n t e r f a c er e t u r n mBinder ;
}p r i v a t e f i n a l IRemoteSe r v i c e . Stub mBinder = new IRemoteSe r v i c e . Stub ( ) {
p u b l i c i n t ge tP id ( ){r e t u r n P roce s s . myPid ( ) ;
}p u b l i c vo i d ba s i cType s ( i n t an In t , l ong aLong , boo l ean aBoolean ,
f l o a t aF loat , doub l e aDouble , S t r i n g aS t r i n g ) {// Does no th i ng
}} ;
}
Connect
IRemoteSe r v i c e mIRemoteServ ice ;p r i v a t e S e r v i c eConne c t i o n mConnection = new Se r v i c eConn e c t i o n ( ) {
// Ca l l e d when the conne c t i on wi th the s e r v i c e i s e s t a b l i s h e dp u b l i c vo i d onSe rv i c eConnec t ed (ComponentName className , IB i n d e r s e r v i c e ) {
// Fo l l ow i ng the example above f o r an AIDL i n t e r f a c e ,// t h i s g e t s an i n s t a n c e o f the IRemo t e I n t e r f a c e , which we can use to
c a l l on the s e r v i c emIRemoteServ ice = IRemoteSe r v i c e . Stub . a s I n t e r f a c e ( s e r v i c e ) ;
}
// Ca l l e d when the conne c t i on wi th the s e r v i c e d i s c o n n e c t s un e xp e c t ed l yp u b l i c vo i d onSe r v i c eD i s c onn e c t e d (ComponentName className ) {
Log . e (TAG, ” S e r v i c e has un e xp e c t ed l y d i s c onn e c t e d ” ) ;mIRemoteServ ice = n u l l ;
}} ;
Problems
• Not easily versionable
• Backward compatibility problems: What if a new parameter ormethod is introduced
• How to pass objects?
• What about input/output streams?
• User Interaction if required, e.g., passphrase input?
Versionable and Backward CompatibleMethod Parameters
Use Intent/Bundle inside of AIDL method definition!
Demo Code
Input-/Outputstreams
Use ParcelFileDescriptors and stream in/out with them using pipes
Demo CodeNote: Not usable inside parameters Bundle!
Objects
• Use Parcelables
• Use versionable Parcelables (seen in Dashclock Widget)
• Put them in new parameters Bundle for passing them around
Demo Code
User Interaction
• A little bit more complicated
• Google’s billing API uses something similar
• Return PendingIntent to client application with predefined setof extras
• Client application can execute this PendingIntent withstartIntentSenderForResult()
• In onActivityResult restart process using newly returnedparameter Bundle
Demo Code (RemoteService)
Process
Demo Code
Custom Permissions
Restricting access to API with custom permissions?
• Extreme Limitations
• Attack scenarios
• https://github.com/commonsguy/cwac-security/blob/
master/PERMS.md
• First one in wins. In other words, the first app (or framework,in the case of the OS’s platform permissions) that defines a<permission> for a given android:name gets to determinewhat the description is and what the protection level is.
• The user is only prompted to confirm a permission if the appbeing installed has a <uses-permission> element, thepermission was already defined by some other app, and theprotection level is not signature.
Custom access control
• On first access ask the user to grant access to API (seePendingIntents)
• Save package name, package signature to OpenKeychain (andoptional settings for this specific app)
• Check against this database when clients bind toOpenKeychain’s service:String[] callingPackages =
getPackageManager().getPackagesForUid(
Binder.getCallingUid());
• Let the user revoke access using a list of granted applications
• Trusted Intents implements similar access control mechanisms:https://dev.guardianproject.info/projects/
trustedintents
UI
UI
Conclusion
• Sophisticated IPC APIs are possible
• Use generic AIDL method definitions
• Instead of method parameters, use Bundles with parameters
• For IPC objects use Parcelables
• Use versionable Parcelables
Questions? Feedback?Pull Requests for OpenKeychain?
https://github.com/open-keychain/open-keychain
Conclusion
• Sophisticated IPC APIs are possible
• Use generic AIDL method definitions
• Instead of method parameters, use Bundles with parameters
• For IPC objects use Parcelables
• Use versionable Parcelables
Questions? Feedback?Pull Requests for OpenKeychain?
https://github.com/open-keychain/open-keychain